Dynamicly changing the staticresource to use on a control.
I'm making a listview that consists of an icon to the left and some text to the right.
I have an enum of possible icontypes, the look of every icontype is defined in a resourcedictionary like this:
<
Rectangle x:Key="file" Fill="Red" Width="20" Height="20" /><
Image x:Key="folder" Width="20" Height="20" Source="hoho.png" />To use one of these items i have an iconcontainer that i use like this:
<
IconContainer Type="{StaticResource folder}" />Is it possible to change folder in the snippet above to something dynamic. When i add an option to my listview i want to specify what type of image that should be used.
I've tried to create a DependencyProperty called icontype and change folder to a datbinding of this property but that didnt work. Like this:
<
IconContainer Type="{StaticResource {Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconType}}">
Answers
- one way is to use ItemTemplateSelector. Define a datatemplate for each possible icontypes and use one depending on image type
Solved it by using a Controltemplate, all i have now is a property for the icontype(the enum) that is binded to the conentcontrol that automaticly selects the DataTemplate that represent this icontype with a DataTemplateSelector.
Like this:
<
DataTemplate x:Key="iconType1">
Rectangle Fill="Blue" Width="20" Height="20" /><
</
DataTemplate><
Style TargetType="{x:Type MyNamespace:EMCMenuOption}">
Setter Property="FocusedTemplate"><
Setter.Value><
ControlTemplate><
Canvas Margin="0,1,0,1" Height="20" Width="190" Background="White"><
<ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}" />
<TextBlock Canvas.Left="25" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Name}" FontSize="16" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="UnFocusedTemplate">
<blablala />
</Setter>
</Style>
Works perfect!
All Replies
- one way is to use ItemTemplateSelector. Define a datatemplate for each possible icontypes and use one depending on image type
Is there no way to do the same thing but for only one item, using an entire collection creates alot of code, both for me and for the skinners.
I found another sollution that works but it doesn't update the icon when i change the resources. I guess i have to do some kind of databinding but i don't know how.
MenuOption.cs
void MenuOption_Loaded(object sender, RoutedEventArgs e) {
ControlTemplate newTemplate; if (iconType == IconType.icon1)
ControlTemplate)Application.Current.MainWindow.Resources["icon1"]; //<--Create binding here? elsenewTemplate = (
ControlTemplate)Application.Current.MainWindow.Resources["icon2"]; //<--Create binding here? this.SetValue(MenuOption.IconTemplateProperty, newTemplate);newTemplate = (
}
public static DependencyProperty IconTemplateProperty = DependencyProperty.Register(
"IconTemplate" , typeof(ControlTemplate) , typeof(MenuOption), new UIPropertyMetadata(new PropertyChangedCallback(iconTemplateChanged))); private static void iconTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){
MenuOption mOption = (MenuOption)d;mOption.IconTemplate = (
ControlTemplate)e.NewValue;}
public ControlTemplate IconTemplate{
get { return this.iconTemplate; } set { this.iconTemplate = value; }}
Window1.xaml:
<
Window.Resources>
CollectionViewSource x:Key="items_list" Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"/><
<
ControlTemplate x:Key="icon1">
Rectangle Fill="Red" Width="20" Height="20" /><
</
ControlTemplate><
ControlTemplate x:Key="icon2">
Rectangle Fill="Yellow" Width="20" Height="20" /><
</
ControlTemplate><
Style TargetType="{x:Type uc:MenuOption}">
Setter Property="Template"><
Setter.Value><
ControlTemplate><
Canvas Margin="0,0,0,3" Width="100" Background="Blue" Height="20"><
Control Canvas.Left="5" Template="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconTemplate}" /><
<
TextBlock Canvas.Left="30" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Name}" /></
Canvas></
ControlTemplate></
Setter.Value></
Setter></
Style></
Window.Resources><
Grid Background="White">
ItemsControl ItemsSource="{Binding Source={StaticResource items_list}}" ><
ItemsControl.Template><
ControlTemplate><
<
ItemsPresenter /></
ControlTemplate></
ItemsControl.Template><
ItemsControl.ItemsPanel>
ItemsPanelTemplate><
<StackPanel Width="100" Height="100" Background="Green" />
</
ItemsPanelTemplate></
ItemsControl.ItemsPanel></
ItemsControl></
Grid>When i change resources, the design of everything changes except for the menuicons.
The icon is this in the above xaml:
<Control Canvas.Left="5" Template="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconTemplate}" />
Another thing i don't realy understand is why you need both an ItemsPanelTemplate and a ControlTemplate for the ItemsControl.
You could add an IconTemplateKey property which would take an object that is the key used on the icon resources. In the property changed callback for the key property, you can call mOption.SetResourceReference(IconTemplateProperty, e.NewValue); This will automatically update the IconTemplate property if the resources change (it is the same as using DynamicResource in xaml).
ItemsPanelTemplate is a simple way to provide a new panel for an ItemsControl without defining the entire ControlTemplate. For example, you can provide an ItemsPanel of <StackPanel Orientation="Horizontal"/> to ListBox to get a horizontal listbox. If you wanted to do this with a control template, you would have to specify a Border, ScrollViewer, and Panel as well as triggers to handle disabled colors.
Solved it by using a Controltemplate, all i have now is a property for the icontype(the enum) that is binded to the conentcontrol that automaticly selects the DataTemplate that represent this icontype with a DataTemplateSelector.
Like this:
<
DataTemplate x:Key="iconType1">
Rectangle Fill="Blue" Width="20" Height="20" /><
</
DataTemplate><
Style TargetType="{x:Type MyNamespace:EMCMenuOption}">
Setter Property="FocusedTemplate"><
Setter.Value><
ControlTemplate><
Canvas Margin="0,1,0,1" Height="20" Width="190" Background="White"><
<ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}" />
<TextBlock Canvas.Left="25" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Name}" FontSize="16" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="UnFocusedTemplate">
<blablala />
</Setter>
</Style>
Works perfect!


