UWP - Icon Picker - combobox

I'm currently learning how to make UWP Apps, and to do so, I'm making an application that allows the user to create notes, categories of notes, etc...
I have a NavigationView in which every category will be listed, and when the user clicks on a specific category, something (I don't know what yet) pops up with a list of all the notes.
I want each category to have an icon, so when the pane of the NavigationView is closed, the user can still click on a category .
My problem is the following :
When the user creates a new category, I want to give him the choice of the icon through a combobox (or something acting the same) with all the possible icons in it.
Is it possible to put icons in a Combobox ?
How can I get the same icons as those I would use for a NavigationViewItem, to use them as item source for my Combobox ?
EDIT :
Here's what I've done : I added an ItemTemplate to my Combobox, using the SymbolIcon component :
<ComboBox x:Name="iconpicker">
<ComboBox.ItemTemplate>
<DataTemplate>
<SymbolIcon Symbol="{Binding symbol}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I also made a simple class :
public class ComboSymbol
{
public Symbol symbol;
}
And here's my code to fill the combobox :
ObservableCollection<ComboSymbol> images = new ObservableCollection<ComboSymbol>();
iconpicker.ItemsSource = images;
images.Add(new ComboSymbol { symbol = Symbol.Accept });
And.. it's almost working.
Picture of the combobox item
As you can see, the symbol is not the one I choosed. And no matter which symbol I pick (in code-behind), there is always this emoji instead.
EDIT 2 :
I was searching where I did something wrong, and apparently it's about my binding. There is a default icon for SymbolIcon component (I just created a SymbolIcon without telling the Symbol I want and this emoji appeared again, so I guess in my case my binding is not good, and because it can't find the Symbol I want, the program used the default icon).
Final edit :
Here was the problem : I just forgot to put the "{ get; set; }" after the members declaration in my class. It's now working !
public Symbol symbol { get; set; } // Fix

There are several UWP controls that can display "icons". Their common parent is an IconElement class and it has the following implementations:
BitmapIcon - displays an image (usually .png) as icon
PathIcon - displays a XAML path as icon
FontIcon - displays a string in a given font as icon
SymbolIcon - displays an icon based on a value from predefined set of system symbols
You can certainly use the same icons for NavigationView as for ComboBox items.
Customizing the ComboBox is quite easy with XAML, because it is fully templateable and you can simply create a custom template:
This assumes Items is a collection of a custom class which has an IconUri property with path to an image used as the icon and a Text property with some text. It will then display a two column layout with an icon on the left and text next to it.

Related

WPF - Creating a custom control with dynamic subcontrols

I am attempting to create a menu/navigation control in WPF that will be used across several applications. The control is intended to reside in a custom window, and will provide the maximize, minimize, close, drag, etc functionality. In addition to the standard "window" functions, the control will should also contain the main "menu" of the application - essentially a collection of buttons that each associate with a command and/or viewmodel - these buttons are custom controls as well (derived from radio buttons).
Essentially, my goal is to be able to add this menu control and it's buttons via XAML in a manner like this (this is pseudocode, to be clear):
<MenuControl Title="ApplicationTitle>
<MenuControl.MenuButtons>
<MenuButton Content="Button1" Command="Command1"/>
<MenuButton Content="Button2" Command="Command2"/>
</MenuControl.MenuButtons>
</MenuControl>
I've gotten to the point where I can get this working correctly for only ONE button. Once I add a second button, I get a "Specified argument was out of the range of the valid values" from my XAML.
Here is the code-behind related to the menu on my custom control:
private static readonly DependencyProperty MenuProperty = DependencyProperty.Register("Menu", typeof(ObservableCollection<NavigationButton>), typeof(CCTNavigationHeader), new FrameworkPropertyMetadata(new ObservableCollection<NavigationButton>()));
public ObservableCollection<NavigationButton> Menu
{
get
{
return (ObservableCollection<NavigationButton>)GetValue(MenuProperty);
}
set
{
SetValue(MenuProperty, value);
}
}
And here is the XAML:
<ItemsControl ItemsSource="{Binding ElementName=ctlCCTNavigationHeader, Path=Menu}"/>
This is the code utilizing the control that works, with only one button:
<Controls:CCTNavigationHeader Title="Test">
<Controls:CCTNavigationHeader.Menu>
<Controls:NavigationButton Content="Test"/>
</Controls:CCTNavigationHeader.Menu>
</Controls:CCTNavigationHeader>
And this is the code using the control that chokes, once I add a second button:
<Controls:CCTNavigationHeader Title="Test">
<Controls:CCTNavigationHeader.Menu>
<Controls:NavigationButton Content="Test"/>
<Controls:NavigationButton Content="Test"/>
</Controls:CCTNavigationHeader.Menu>
</Controls:CCTNavigationHeader>
I know I must be doing something incorrectly here, but I haven't been able to find any examples of accomplishing this type of solution anywhere. Can anyone familiar with creating custom user controls in WPF point me in the right direction?
Figured this one out. I wasn't initializing the Menu collection when creating the control. The following code fixed it:
public CCTNavigationHeader()
{
InitializeComponent();
Menu = new ObservableCollection<NavigationButton>(); //this line
}

Creating a dynamic seach using MvvM and WPF

I am fairly new to mvvm and WPF so I am looking for some pointers to achieve the following.
I would like to create a search section in my app that builds up the search options based on whatever the users selects as their criteria.
So for example the first combo box of the search offers the top level of choices:
Date of Message
Gateway
Direction
Etc..
......
The second section is my operator
So, for example if Date of Message is selected then the user is offered another combo box of choices
Is Between
Last Week
Last Month
Etc..
The last section of the search is based on the operator above, so if Is Between is selected the form displays two Date Pickers from and to. If on the other hand Last Week is selected then nothing is displayed as the search can directly call my SetActionLogsForLastWeek() method once I click my search button.
If the user selects Gateway from the initial list then another combo box is build with a list of choices based on gateways.
I am looking for a tutorial or previous post that points me in the right direction on achieving my goal of building WPF elements based on selection choices from other elements.
Thanks
This is a rather extensive question, and as such there is no definitive answer. I will describe how I would handle this problem. Keep in mind that this might not be the best solution out there.
In order to render the controls which depend on the first combo box use data templates and distinct view models. In the resource section of your main view, or an external resource if you have defined one, write something like this:
<DataTemplate DataType="{x:Type vm:YourViewModel}"> <vw:YourView /> </DataTemplate>
You will have to import the namespaces containing your viewmodels and views (vm: and vw: here). Using content-controls you can render views depending on their viewmodels:
<ContentControl Content="{Binding CurrentViewModel}"></ContentControl>
In your code behind, you will have to have a ViewModel which you can bind to. Depending on the selection of the first combo box, you can now swap out the ViewModel in the code behind in order to render the dependent combo boxes - or nothing at all!
In order to illustrate, let me provide some sample code. Lets start with you main view model. Thats the one containing the collection the first combo box binds to (e.g. the strings "Date of Message","Gateway"...)
public class MainViewModel : BaseViewModel {
public IObservableCollection comboBoxItems;
public BaseViewModel ControlViewModel {get; set;}
private String selectedItem;
public String SelectedItem {
get {
return selectedItem;
}
set {
selectedItem = value;
OnPropertyChanged("SelectedItem");
ChangeControls();
}
}
private void ChangeControls(){
switch(selectedItem):
//swap out the control view model here e.g.
controlViewModel = new GateWayControlViewModel();
}
}
Btw, BaseViewModel is an abstract class which all view models inherit from. It implements INotifyPropertyChanged.
In your main view it is enough to have content control binding to the control view model, as well as the first combo box:
In your resources.xaml you define the data template, as discussed before.
<DataTemplate DataType="{x:Type vw:GatewayControlViewModel}"> <vw:GatewayView /> </DataTemplate>
This will render the GateWayView if the ViewModel, which the ContentControl in the main view is bound to is equal to GateWayControlViewModel. Finally, your GatewayView could look like this:
<ComboBox ItemsSource="{Binding Gateways}"
SelectedValue="{Binding SelectedGateway}" />
Obviously, you will have to make sure your GatewayControlViewModel actually contains the items and properties mentioned in the view. It will also need to derive from BaseViewModel.
I hope this gives you some ideas. Additionally, you might find this link useful (as it contains some very useful tips on how to approach MVVM).
If you want to implement Search in Collections for example in as in Combobox or Grid you should read a bit about ICollectionView. The ICollectionView will allow you to filter collection based on your search criteria. In your example you can also do this by handling selection changed events at the viewmodel and create method to update your data based on selected inputs.

Replicating WPF TabControl selected TabItem design time behavior for a custom control

I'm developing a custom control which shows an inline popup window and I would like to use a similar technique as the TabControl employes so that only popup windows that are selected within the designer or more commonly by placing the cursor within the popup declaration in XAML that it is visualized right within the desiger without having to run the application or change any runtime values by hand.
I've started by duplicating the implementation of the TabControl which I have successfully mimicking everything but it is all copied from Reflector output and Stylesnooper. I've renamed all of the control parts and then replaced the default templates so that the main control uses an ItemsPresenter instead of a ContentPresenter to show the individual popup controls within a Grid panel overlayed on top of one another. So far this is working great too. The problem is that somewhere along the line I lost the ability to have the designer follow the item that is selected in the XAML editor.
Either an explanation of how the TabControl's design time behavior functionality actually works to describe the selected TabItem behavior that I described above or just some pointers on how one could achieve what I'm tryign to do would be great.
To solve a similar problem, I had to create design time support for my custom tab control. Here is a link for WPF Designer Extensibility.
Basically, I created a PrimarySelectionAdornerProvider to handle click interaction and a FeatureConnector<> / FeatureProvider pair for selection changes (including selection changes made in the xaml editor).
The feature provider / connector:
[FeatureConnector(typeof(AutoTabPageSelectionFeatureConnector))]
class AutoTabPageSelectionFeatureProvider : FeatureProvider
{
public AutoTabPageSelectionFeatureProvider()
: base()
{
// sole purpose is to register the connector
}
}
class AutoTabPageSelectionFeatureConnector : FeatureConnector<AutoTabPageSelectionFeatureProvider>
{
public AutoTabPageSelectionFeatureConnector(FeatureManager manager)
: base(manager)
{
SelectionOperations.Subscribe(this.Context, SelectionChanged);
}
private void SelectionChanged(Selection selection)
{
if (selection.PrimarySelection != null)
{
// navigate tree to find parent (custom tab page and custom tab control)
for (ModelItem item = selection.PrimarySelection; item != null; item = item.Parent)
{
// once found, select appropriate tab
}
}
}
}
Edit (more info):
This Microsoft link has a number of links to walk-throughs that should help. Here are the basic steps to get started:
Create a new project, MyAssembly.VisualStudio.Design.dll.
The library should compile to the same location as MyAssembly.dll (important).
Add references to Microsoft.Windows.Design.Extensibility and Microsoft.Windows.Design.Interaction.
Add a reference to your control library.
Create a class called Metadata
Code:
internal class Metadata : IProvideAttributeTable
{
// Accessed by the designer to register any design-time metadata.
public AttributeTable AttributeTable
{
get
{
AttributeTableBuilder builder = new AttributeTableBuilder();
// Add the adorner provider to the design-time metadata.
builder.AddCustomAttributes(
typeof(MyControl), // rename to your control's name
new FeatureAttribute(typeof(MyPrimaryAdornerProvider)), // rename to whatever you will call your PrimaryAdornerProvider
new FeatureAttribute(typeof(AutoTabPageSelectionFeatureProvider)) // rename to whatever you will call your SelectionFeatureProvider
);
return builder.CreateTable();
}
}
}
Create a class MyPrimaryAdornerProvider from PrimarySelectionAdornerProvider (rename to whatever you want). See link for good walk-through.
Create the AutoTabPageSelectionFeatureProvider and AutoTabPageSelectionFeatureConnector from the example above.

WPF Custom Control

I have a view with some controls and a viewbox. At the moment in the viewbox is a grid and a graphic at the bottom. The application reads a XML-file and refreshs the content of the grid and the graphic for every node in the XML-file.
Now the application not only have to show a grid with a graphic. Depending on the XML-node, the application should show a grid with a graphic like now or a grahpic and at the bottom 2 lines of text.
You explained what your application is, but you didn't ask a question. Please state the question, and I can try to give you a better answer.
My best guess is "how do I do that? Do I need to write a custom control?" If that is what you are asking, you probably don't.
Usually you don't need a custom control to make a specialized view for a listbox, listview, or gridview. You can often use data templates, control templates or styles to achieve what you are looking for.
I am not sure if this is a good resource, but the XAML looks like it may be a good starting point for learning how to do control templates:
http://ligao101.wordpress.com/2007/07/27/customizing-listview-in-wpf-part-i/
Simply googling for any of those terms ("ListView data template", etc) will probably get you some good information.
Edit:
From the comments, you are trying to support one of two types of data in the same space in the UI, depending on what is in your XML file:
Image Only
Image, plus two lines of text
One way to solve this would be to create a view model for your XML items, and bind the items to those view models:
public class XmlItemViewModel // Call this something more appropriate to your app
{
public Visibility TextVisibility { get; set; }
public string Text1 { get; set; }
public string Text2 { get; set; }
public Image Picture { get; set; }
}
If you already have a different class that has this data, keep it, and make the view model read properties off that class.
Bind the XAML TextBlock Visibility property to "{Binding TextVisibility}", and it should work. If you set the viewmodel property "Visibility.Collapsed", the text blocks will go away, and your ViewBox should shrink to fit only the image.
If you do this, you don't need a custom control, just a custom ViewModel class.
If it doesn't seem to collapse correctly, you could wrap your image and text blocks with a StackPanel or WrapPanel.

How to display attached properties in Property Browser of blend for silverlight?

I created couple of custom controls and their childresn correctly shows the attached properties in Property Browser for WPF, but in silverlight none of the attached properties appear in Property Brower.
How to add design time support for attached properties in silverlight?
Looks like there might be some attributes to work with to make custom properties appear in the designer:
http://blogs.msdn.com/jnak/archive/2008/01/17/showing-attached-properties-in-the-cider-wpf-designer.aspx
I have not tried it though, not sure if it will work with Silverlight.
Henrik's definitely works for WPF in VS2015/Blend. Just for reference, I'm adding some of the info from the linked article because so many times links to blogs die after a number of years.
AttachedPropertyBrowsableWhenAttributePresentAttribute
This attribute allows you to specify that your attached property show
up in the Property Browser when the selected item has a given
attribute applied to it.  If the attribute has a default value, that
value also has to be different from the default value.
In the example above that passes in “MyCustomAttribute” as the
attribute to look for, when CustomLabel below is selected in the
designer, the Property Browser will show the ShowWhenCustomAttribute
attached property however it will not when
CustomLabelNoCustomAttribute is selected:
   
[MyCustomAttribute]
public class CustomLabel : Label
{
}
public class CustomLabelNoCustomAttribute : Label
{
}
AttachedPropertyBrowsableForChildrenAttribute
This attribute indicates that the attached property should be available for the children of the given control.  There are two main flavors for this attribute.  One that includes descendants and one that does not. As you might expect including descendants refers to including all children or simply the direct children of the control.
[AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants=true)]
public static int GetShowForChildrenDeep(UIElement element)
{
    return (int)element.GetValue(ShowForChildrenDeepProperty);
}
AttachedPropertyBrowsableForType
This attribute allows you to specify that your attached property show up when a given type or types derived from that type are selected in the designer.  The following sample would make your attached property show up when any Grid, derived Grid, Button or derived Button is selected.
[AttachedPropertyBrowsableForType(typeof(Grid))]
[AttachedPropertyBrowsableForType(typeof(Button))]
public static int GetShowForTypes(UIElement element)
{
    return (int)element.GetValue(ShowForTypesProperty);
}
And here are the MSDN doc links:
https://msdn.microsoft.com/en-us/library/system.windows.attachedpropertybrowsableforchildrenattribute(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.attachedpropertybrowsablefortypeattribute(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.attachedpropertybrowsablewhenattributepresentattribute(v=vs.110).aspx

Resources