I tried different ways to solve the Problem. First I bound in my ViewModel the MainColor as String,Color,Brush and tried to bind it to the Border -> don't worked for me. Second was an Converter, but I couldn't bind correct the string to activate the converter. The only thing that worked with the Bind the MainColor as string to a Label style, that I have also in the same Resource. So now the change in the Label works, but not in the Listbox.
My View:
<Page.Resources>
<ResourceDictionary Source="/Resources/ResourcePageCuttingData.xaml"></ResourceDictionary>
</Page.Resources>
<ListBox ItemsSource="{Binding Material}" SelectedItem="{Binding SelectedMat, Mode=TwoWay}" Style="{StaticResource styleMat}" Grid.Column="5" Grid.Row="1" Margin="20,0"></ListBox>
<Label Style="{StaticResource Label_Search}" Content="{DynamicResource so_lbl_cm}" ></Label>
My Listbox in ResourceDictonary:
<Style x:Key="styleMat" TargetType="{x:Type ListBox}">
<Setter Property="OverridesDefaultStyle" Value="True"></Setter>
<Setter Property="ItemContainerStyle" Value="{DynamicResource ResourceKey=styleLocMschItem}"></Setter>
<Setter Property="ItemTemplate" Value="{StaticResource ResourceKey=ResultMatDataTemplate}"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border BorderBrush="#5A5A5A" BorderThickness="1" CornerRadius="4">
<ScrollViewer Margin="1">
<ItemsPresenter Margin="1"></ItemsPresenter>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ResultMatDataTemplate">
<TextBlock Text="{Binding}"
FontSize="20"
></TextBlock>
</DataTemplate>
<Style x:Key="styleLocMachItem" TargetType="{x:Type ListBoxItem}">
<Setter Property="OverridesDefaultStyle" Value="True"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Border x:Name="hover"
Background="YellowGreen"
Visibility="Collapsed">
</Border>
<Border x:Name="orginal"
Background="{Binding MainColor}">
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="highlight"
Property="Visibility"
Value="Visible">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The MainColor is not working in Border x:Name="original"
My Label:
<Style x:Key="Label_Search" TargetType="{x:Type Control}">
<Setter Property="Background" Value="{Binding MainColor}" />
</Style>
Here the MainColor works fine
My ViewModel:
public CuttingSpeed_ViewModel()
{
switch (value)
{
case "Fast":
MainColor = "Pink";
break;
case "Slow":
MainColor = "Yellow";
break;
default:
MainColor ="Red";
break;
}}
private string _MainColor;
public string MainColor
{
get { return _MainColor; }
set { _MainColor = value; OnPropertyChanged("MainColor"); }
}
public IEnumerable<string> Material
{
get { return _Material; }
set { _Material = value; OnPropertyChanged("Material"); }
}
private string _SelectedMat;
public string SelectedMat
{
get { return _SelectedMat; }
set
{..}}
I think there should be something in xaml that don't allow me to get the value MainColor.
The MainColor property should return a Brush:
public CuttingSpeed_ViewModel()
{
switch (value)
{
case "Fast":
MainColor = Brushes.Pink;
break;
case "Slow":
MainColor = Brushes.Yellow;
break;
default:
MainColor = Brushes.Red;
break;
}
}
private Brush _MainColor;
public Brush MainColor
{
get { return _MainColor; }
set { _MainColor = value; OnPropertyChanged("MainColor"); }
}
You should also bind to the DataContext of the parent ListBox:
<Border x:Name="orginal" Background="{Binding DataContext.MainColor,
RelativeSource={RelativeSource AncestorType=ListBox}}">
Related
I have a ComboBox with an ItemTemplateSelector, using 2 different DataTemplates, one for when its drop down is visible and another when it is not. For the drop down template, each ComboBox item is represented by a TextBlock and a Button that should only be visible whenever that item is focused/highlighted/mouse over. This is what I've tried:
<ComboBox x:Name="Windows" ItemsSource="{Binding Windows}" SelectedItem="{Binding Window}" Focusable="False" MaxDropDownHeight="238">
<ComboBox.ItemTemplateSelector>
<s:ComboBoxItemTemplateSelector>
<s:ComboBoxItemTemplateSelector.SelectedTemplate>
<DataTemplate>
<TextBlock Text="{Binding TitleShort}" ToolTip="{Binding Title}" />
</DataTemplate>
</s:ComboBoxItemTemplateSelector.SelectedTemplate>
<s:ComboBoxItemTemplateSelector.DropDownTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding TitleShort}" />
<Button Content="X">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=Windows}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</DataTemplate>
</s:ComboBoxItemTemplateSelector.DropDownTemplate>
</s:ComboBoxItemTemplateSelector>
</ComboBox.ItemTemplateSelector>
<ComboBox.ItemContainerStyle>
<Style BasedOn="{StaticResource MaterialDesignComboBoxItemStyle}" TargetType="ComboBoxItem">
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock Text="{Binding Title}" />
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
public class ComboBoxItemTemplateSelector : DataTemplateSelector
{
public DataTemplate SelectedTemplate { get; set; }
public DataTemplate DropDownTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
ComboBoxItem comboBoxItem = GetVisualParent<ComboBoxItem>(container);
if (comboBoxItem == null)
{
return SelectedTemplate;
}
return DropDownTemplate;
}
private static T GetVisualParent<T>(object childObject) where T : Visual
{
DependencyObject child = childObject as DependencyObject;
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}
}
ComboBox generates ComboBoxItem as a container for every item in its itemssource. You can bind to its properties with RelativeSource binding.
This should get you the expected behavior:
<Button Content="X">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
In WPF I'm trying to create a "flag" control that displays a checkmark or an X based on a bound dependency property (Flag)
<UserControl x:Name="Root" (Other user control stuff)>
<ContentControl Height="20" x:Name="flagHolder">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="False">
<Setter Property="Content" Value="{StaticResource XIcon}" />
<Setter Property="Foreground" Value="Crimson"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="True">
<Setter Property="Content" Value="{StaticResource CheckIcon}" />
<Setter Property="Foreground" Value="ForestGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</UserControl>
On startup every icon is correct (I have several of these controls, each bound to different values). However, when I toggle a few (one that was "off" turns "on" and the one currently "on" turns "off") I see two things:
The control that was turned "on" has become a green check (as desired)
The control that was turned "off" is now just blank
Inspecting the visual tree seems to indicate that everything is working (though I could easily be missing something here), and the order of the triggers doesn't seem to matter. What am I doing wrong?
Here is an example icon, the path geometry is removed since its just noise:
<Viewbox x:Key="CheckIcon" x:Shared="False">
<Path Style="{StaticResource IconPathStyle}">
<Path.Data>
<PathGeometry Figures="Bunch of SVG" FillRule="NonZero"/>
</Path.Data>
</Path>
</Viewbox>
I'm unable to reproduce your issue, but here what I have and it's working:
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Viewbox x:Key="CheckIcon" x:Shared="False">
<Canvas Height="24" Width="32">
<Path Width="7.85446" Height="8.57578" Canvas.Left="-0.0522281" Canvas.Top="-0.100391" Stretch="Fill" StrokeThickness="1.04192" StrokeMiterLimit="2.75" Stroke="#FF000000" Data="F1 M 0.468732,4.66838L 3.03345,7.95443L 7.28127,0.420569"/>
</Canvas>
</Viewbox>
<Viewbox x:Key="XIcon" x:Shared="False">
<Canvas Height="24" Width="32">
<Path Data="M0,0 L1,1 M0,1 L1,0" Stretch="Fill" Stroke="Black" StrokeThickness="3" Width="12" Height="12" />
</Canvas>
</Viewbox>
</Application.Resources>
</Application>
YesNo.xaml
<UserControl x:Class="WpfApplication1.YesNo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="Root">
<ContentControl Height="20" Name="flagHolder">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="False">
<Setter Property="Content" Value="{StaticResource XIcon}" />
<Setter Property="Foreground" Value="Crimson"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="True">
<Setter Property="Content" Value="{StaticResource CheckIcon}" />
<Setter Property="Foreground" Value="ForestGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</UserControl>
YesNo.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class YesNo : UserControl
{
public YesNo()
{
InitializeComponent();
}
public static readonly DependencyProperty FlagProperty = DependencyProperty.Register(
"Flag", typeof(bool), typeof(YesNo), new PropertyMetadata(default(bool)));
public bool Flag {
get {
return (bool) GetValue(FlagProperty);
}
set {
SetValue(FlagProperty, value);
}
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="" Width="400" Height="400">
<StackPanel Orientation="Vertical" Margin="50">
<wpfApplication1:YesNo Flag="{Binding Flag1}"/>
<wpfApplication1:YesNo Flag="{Binding Flag2}"/>
<wpfApplication1:YesNo Flag="{Binding Flag2}"/>
<wpfApplication1:YesNo Flag="{Binding Flag1}"/>
<Button Content="Toggle" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : INotifyPropertyChanged
{
private bool _flag1;
private bool _flag2;
public MainWindow()
{
InitializeComponent();
DataContext = this;
Flag1 = true;
Flag2 = false;
}
public bool Flag1 {
get {
return _flag1;
}
set {
_flag1 = value;
OnPropertyChanged();
}
}
public bool Flag2 {
get {
return _flag2;
}
set {
_flag2 = value;
OnPropertyChanged();
}
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
Flag1 = !Flag1;
Flag2 = !Flag2;
}
}
How it looks like:
Video: http://www.screencast.com/t/J5IY7DR3Ry
I have a listbox "listBox_Results" and several ItemTemplates(one of them ItemTemplateStyle1), in my ItemContainerStyle I'm setting Template property for item. So I want change my ItemTemplate in trigger "IsSelected".
(in common sense: I want my listboxitem change size and content display on selection, by dynamicly setting diffrent ItemTemplate)
Do you have any solutions?
Best regards
upd:If you think this question is unclear or not useful, most apreciate if tell you me why, before you minus
Code:
<ListBox Name="listBox_Results"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderThickness="0"
Margin="2"
Grid.Row="0"
ItemTemplate="{StaticResource ItemTemplateStyle1}"
ItemsSource="{Binding}" >
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,2,2,2"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" Margin="1" SnapsToDevicePixels="true" CornerRadius="3" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" >
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
#E1E1E1
</Setter.Value>
</Setter>
...
First, take out your inline styling and create a ResourceDictionary to keep things together. This will also help with the template switch I am suggesting.
In the Resource Dictionary, you will define the two templates that you want (the selected and unselected list item templates), the style of the list item and the list box itself. I am abbreviating the code, just to show how I would put the items together.
In the ResourceDictionary
<ControlTemplate x:Key="unselectedTemplate" TargetType="{x:Type ListBoxItem}">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="selectedTemplate" TargetType="{x:Type ListBoxItem}">
<Grid>
<ContentPresenter Margin="3"/>
</Grid>
</ControlTemplate>
<Style x:Key="listboxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" Value="{StaticResource unselectedTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Template" Value="{StaticResource selectedTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="listBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource listboxItemStyle}"/>
</Style>
Then, when you are creating your list box on the page... just reference the list box style key.
<ListBox Name="listbox_Results" Style="{StaticResource listBoxStyle}" ItemsSource="{Binding}"/>
Make sure the ControlTemplates are defined before the styles, I found when I don't I run into errors. Also, this keeps your layout page cleaner, and the styles are easier to reuse if you need to use them again.
I uploaded a very basic example here.
You have to use an Data template selector which will select a particular data template according to the conditions in your selector.
You have to write the data templates in xaml with separate names and select them from the DataTemplateSelector class file.
For that you need to inherit from the base class DataTemplateSelector
I will share some sample code with you. Please check this and you will get an idea of how to use an item template selector.
XAML :
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="NormalUserDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="PremiumUserDataTemplate">
<StackPanel Background="LightBlue">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<local:PremiumUserDataTemplateSelector x:Key="myPremiumUserDataTemplateSelector" />
</Window.Resources>
<Grid>
<ListView x:Name="myListView" ItemTemplateSelector="{StaticResource myPremiumUserDataTemplateSelector}">
</ListView>
</Grid>
</Window>
Code behind :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<User> users = new List<User>();
for (int i = 0; i < 10; ++i)
{
var user = new User { ID = i, Name = "Name " + i.ToString(), Age = 20 + i };
if (i == 2 || i == 4)
{
user.IsPremiumUser = true;
}
users.Add(user);
}
myListView.ItemsSource = users;
}
}
public class PremiumUserDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement elemnt = container as FrameworkElement;
User user = item as User;
if(user.IsPremiumUser)
{
return elemnt.FindResource("PremiumUserDataTemplate") as DataTemplate;
}
else
{
return elemnt.FindResource("NormalUserDataTemplate") as DataTemplate;
}
}
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool IsPremiumUser { get; set; }
}
I have implemented IDataErrorInfo to my custom Controls' ViewModels. Everything works fine (border is being drawn red, a tooltip with the error is being shawn), but i was wondering if there is a way to have two different Validation.ErrorTemplates for errors and warnings.
My Custom Control Style (with the Validation.ErrorTemplate)
<Style TargetType="{x:Type controls:CustomTextBoxNumeric}">
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
My Custom Control ViewModel (INotifyPropertyChanged is implemented at the base ViewModel)
public class CustomTextBoxNumericViewModel : BaseComponentViewModel, IDataErrorInfo
{
private decimal? decimalValue;
private bool hasErrors;
private bool hasWarnings;
public CustomTextBoxNumericViewModel()
{
}
[DataMember(EmitDefaultValue = false)]
public decimal? DecimalValue
{
get { return this.decimalValue; }
set { this.decimalValue = value; this.Changed("DecimalValue"); this.Changed("HasErrors"); }
}
[DataMember(EmitDefaultValue = false)]
public bool HasErrors
{
get { return this.hasErrors; }
set { this.hasErrors = value; this.Changed("HasErrors"); this.Changed("DecimalValue"); }
}
[DataMember(EmitDefaultValue = false)]
public bool HasWarnings
{
get { return this.hasWarnings; }
set { this.hasWarnings = value; this.Changed("HasWarnings"); this.Changed("DecimalValue"); }
}
#region IDataErrorInfo Implementation
public string Error
{
get
{
throw new NotImplementedException();
}
}
public string this[string propertyName]
{
get
{
if (propertyName == "DecimalValue")
{
if (HasErrors)
{
return this.ErrorsField;
}
if (HasWarnings)
{
return this.WarningsField;
}
if (DecimalValue < 0)
{
return "Must be greater than 0";
}
}
return string.Empty;
}
}
#endregion
}
I managed to solve my issue using ControlTemplate resources.
My style changed to:
<Style TargetType="{x:Type controls:CustomTextBoxNumeric}">
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
<DataTrigger Binding="{Binding Path=ViewModel.HasWarnings, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource EntypoWarningTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ViewModel.HasErrors, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource EntypoErrorTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
The ControlTemplates:
<ControlTemplate x:Key="MyErrorTemplate" TargetType="{x:Type Control}">
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
<ControlTemplate x:Key="MyWarningTemplate" TargetType="{x:Type Control}">
<DockPanel LastChildFill="True">
<Border BorderBrush="Orange" BorderThickness="1">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
I have a popup, where I want to display different things depending on various buttons which are clicked. To do this I've added a ContentPresenter nad in this ContentPresenter I've got an TemplateSelector. My problem is that as far as I can see it only checks which template to use the first time my popUp is run and uses this template from then on. Is there a way to get the code to change the template to use?
The code I've got so far is (xaml):
<Popup IsOpen="{Binding IsOpen}" Height="{Binding Height}" Width="{Binding Width}">
<Grid>
<ContentPresenter x:Name="CP" Loaded="CP_Loaded">
<ViewModel:PopUpTemplateSelector x:Name="PUT" Content="{Binding}">
<ViewModel:PopUpTemplateSelector.View1>
<DataTemplate>
<View:View1/>
</DataTemplate>
</ViewModel:PopUpTemplateSelector.View1>
<ViewModel:PopUpTemplateSelector.View2>
<DataTemplate>
<View:View2/>
</DataTemplate>
</ViewModel:PopUpTemplateSelector.View2>
<ViewModel:PopUpTemplateSelector.View3>
<DataTemplate>
<View:View3/>
</DataTemplate>
</ViewModel:PopUpTemplateSelector.View3>
<ViewModel:PopUpTemplateSelector.View4>
<DataTemplate>
<View:View4/>
</DataTemplate>
</ViewModel:PopUpTemplateSelector.View4>
<ViewModel:PopUpTemplateSelector.View5>
<DataTemplate>
<Design:View5/>
</DataTemplate>
</ViewModel:PopUpTemplateSelector.View5>
</ViewModel:PopUpTemplateSelector>
</ContentPresenter>
</Grid>
</Popup>
and my popUpTemplateSelector(C#) is
public class PopUpTemplateSelector : DataTemplateSelector
{
public DataTemplate View1{ get; set; }
public DataTemplate View2 { get; set; }
public DataTemplate View3 { get; set; }
public DataTemplate View4 { get; set; }
public DataTemplate View5 { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
PopUpViewModel Pop = item as PopUpViewModel;
if(Pop.TemplateToUse == "View1")
{
return View1;
}
else if(Pop.TemplateToUse == "View2")
{
return View2;
}
else if(Pop.TemplateToUse.Equals("View3"))
{
return View3;
}
else if (Pop.TemplateToUse.Equals("View4"))
{
return View4;
}
else if(Pop.TemplateToUse.Equals("View5"))
{
return View5;
}
return null;
}
}
I would suggest you use DataTriggers bound to TemplateToUse property on the ViewModel to update ContentTemplate. And also use ContentControl instead of ContentPresenter
<Popup IsOpen="{Binding IsOpen}" Height="{Binding Height}" Width="{Binding Width}">
<Grid>
<Grid.Resources>
<DataTemplate x:Key="View1Template">
<View:View1/>
</DataTemplate>
<DataTemplate x:Key="View2Template">
<View:View2/>
</DataTemplate>
<DataTemplate x:Key="View3Template">
<View:View3/>
</DataTemplate>
<DataTemplate x:Key="View4Template">
<View:View4/>
</DataTemplate>
<DataTemplate x:Key="View5Template">
<Design:View5/>
</DataTemplate>
<Style x:Key="ContentStyle" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=TemplateToUse}" Value="View1">
<Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TemplateToUse}" Value="View2">
<Setter Property="ContentTemplate" Value="{StaticResource View2Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TemplateToUse}" Value="View3">
<Setter Property="ContentTemplate" Value="{StaticResource View3Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TemplateToUse}" Value="View4">
<Setter Property="ContentTemplate" Value="{StaticResource View4Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=TemplateToUse}" Value="View5">
<Setter Property="ContentTemplate" Value="{StaticResource View5Template}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ContentControl x:Name="CP" Loaded="CP_Loaded" Style="{StaticResource ContentStyle}" Content="{Binding}" />
</Grid>
</Popup>