Listbox DataTemplate clear textbox value on selection - c#

For my ListBox I have a DataTemplate:
<DataTemplate x:Key="lbTemplate" DataType="{x:Type ListBoxItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Naam, Mode=OneWay}" VerticalAlignment="Center" />
<TextBox TextAlignment="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=IsSelected, Converter={StaticResource BoolToAlignment}}"
Text="{Binding Path=Aantal, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, TargetNullValue=0}"
</Grid>
</DataTemplate>
Which the properties are bound to:
public class menuItem
{
public int? Aantal { get; set; }
public string Naam { get; set; }
}
How can I clear the TextBox value if the corresponding ListBoxItem is selected without losing my binding to the Aantal? property?

Use Style with DataTrigger:
<Style TargetType="TextBox" x:Key="tbStyle">
<Setter Property="Text" >
<Setter.Value>
<Binding Path="Aantal" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" />
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=IsSelected}" Value="True">
<Setter Property="Text" Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
EDIT
To reset (clear) the bound Aantal property after selection of ListBoxItem:
Add IsSelected flag to your item class, bind it to ListBoxItem.IsSelected property by adding the following style to your ListBox:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListBox.ItemContainerStyle>
Then in IsSelected setter, add code: if (value) { this.Aantal = ""; }

Related

How to bind property of dynamically created components of a user control to another component?

I have a user control which creates a set of radio buttons based on a list. The radio buttons are created using data template.
<UserControl.Resources>
<SelectableItem:SelectableItem x:Key="vm"></SelectableItem:SelectableItem>
<src:RadioButtonCheckedConverter x:Key="RadioButtonCheckedConverter" />
<CollectionViewSource
Source="{Binding Source={x:Static Application.Current}, Path=ItemDescription}"
x:Key="ListingDataView" />
<DataTemplate x:Key="GroupingHeaderTemplate">
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource GroupHeaderStyle}"/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ItemsControl Name="RadioGroup" AutomationProperties.Name="RadioGroup" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton
GroupName="{Binding Path=ItemType}"
Content="{Binding Path=ItemDescription}"
FlowDirection="RightToLeft"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Style="{DynamicResource CustomRadioButton}" Margin="20,0" Checked="RadioButton_Checked" Tag="{Binding Path=ItemDescription, Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
I use this in a window where I need to change the visibility of a component (stack panel) based on the selected radio button.
<uc:CommonRadioButtonGroup x:Name="SelectionButtonsGroup" ></uc:CommonRadioButtonGroup>
I am trying to change the visibility using style triggers.
<Style x:Key="spStyle" TargetType="StackPanel" >
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static Local:EngineModes.PresentMode}}" Value="Stop">
<Setter Property="StackPanel.Visibility" Value="Hidden" />
</DataTrigger>
<DataTrigger Binding="{Binding Source={x:Static Local:EngineModes.PresentMode}}" Value="Wait">
<Setter Property="StackPanel.Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Source={x:Static Local:EngineModes.PresentMode}}" Value="Go">
<Setter Property="StackPanel.Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
I cannot figure out a way to implement the viewmodel for this one. I tried this one:
public class EngineModes : INotifyPropertyChanged
{
public static List<SelectableItem> Modes { get; set; } = new List<SelectableItem>();
public static string PresentMode { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyInfo)
{
App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyInfo));
}
));
}
}
where "Modes" are the options of the radio button. But it simply does not work.
Ultimately, on selecting a mode using radio button, the visibility of the stack panel must be modified.
Please comment on the correctness of the code.
Edit:
Here is the ItemSource for the user control added in codebehind:
SelectionButtonsGroup.RadioGroup.ItemsSource = EngineModes.Modes;
this.DataContext = EngineModes.PresentMode;
I updated the style as
<Style x:Key="sprecStyle" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource engineModes}, Path=PresentMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="Stop">
<Setter Property="StackPanel.Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding Source={StaticResource engineModes}, Path=PresentMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="Wait">
<Setter Property="StackPanel.Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Source={StaticResource engineModes}, Path=PresentMode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="Go">
<Setter Property="StackPanel.Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
And added a separate notified event for static property change:
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged
= delegate { };
public static void NotifyStaticPropertyChanged(string propertyName)
{
StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName));
}
and called it where the engine mode is updated.
EngineModes.NotifyStaticPropertyChanged("PresentMode");
And voila! It worked.

WPF Datagrid bind data list to a template column combobox

I've been searching for hours on how to bind data to combobox in a datagrid template column. I found some in the site but nothing seems to work. Here's what I've done so far:
public partial class CashReceipt : UserControl
{
private ObservableCollection<CashItem> itemsList;
private ObservableCollection<string> accounts;
public CashReceipt()
{
InitializeComponent();
itemsList = new ObservableCollection<CashItem>();
accounts = new ObservableCollection<string>()
{
"5710",
"6010",
"6510",
"7010"
};
for (int i = 0; i < 5; ++i)
{
CashItem item = new CashItem();
itemsList.Add(item);
}
clDatagrid.ItemsSource = itemsList;
}
}
public struct CashItem
{
public string account { get; set; }
public string description { get; set; }
public decimal amount { get; set; }
}
}
The XAML is
<UserControl x:Class="CashLedgerApp.CashReceipt"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CashLedgerApp"
mc:Ignorable="d"
MinHeight="320" HorizontalAlignment="Stretch">
<UserControl.Resources>
<CollectionViewSource x:Key="AccountsList" Source="{Binding Path=accounts}"/>
</UserControl.Resources>
<Border Margin="100,20" BorderBrush="gray" BorderThickness="0.5">
<Grid Background="White">
<DataGrid x:Name="clDatagrid" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="8" Margin="10,0" VerticalAlignment="Stretch" MinHeight="30" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="False" CanUserAddRows="True">
<DataGrid.Resources>
<Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="0,0,1,0"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<!--<DataGridComboBoxColumn x:Name="clAccount" Header="Compte No" Width="1*" SelectedValuePath="{Binding account}" SelectedValueBinding="{Binding Path=account}"/>-->
<DataGridTemplateColumn Header="Compte No" Width="1*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource AccountsList}}"
SelectedItem="{Binding account}"
DisplayMemberPath="account"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Description" Width="3*" Binding="{Binding description}"/>
<DataGridTextColumn Header="Montant" Width="1.5*" Binding="{Binding amount}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Border>
</UserControl>
When I execute this program, the combobox in the template column is always empty. The data in the accounts list is just a sample to make things work. I'll use data from database in the final version of the code. But I need to make it work first.
Thanks.
UPDATE
I made changes as you suggested #ASh, here is the C# and XAML (I added some data to the itemList collection, as expected, those data are displayed in the grid but the ComboBox in the DataGridTemplateColumn are still empty):
public partial class CashReceipt : UserControl
{
public ObservableCollection<CashItem> itemsList;
public ObservableCollection<string> Accounts;
public CashReceipt()
{
InitializeComponent();
itemsList = new ObservableCollection<CashItem>();
Accounts = new ObservableCollection<string>()
{
"5710",
"6010",
"6510",
"7010"
};
for (int i = 0; i < 5; ++i)
{
CashItem item = new CashItem();
item.description = "Achats";
item.amount = 250000;
itemsList.Add(item);
}
clDatagrid.ItemsSource = itemsList;
}
}
public struct CashItem
{
public string account { get; set; }
public string description { get; set; }
public decimal amount { get; set; }
}
<UserControl x:Class="CashLedgerApp.CashReceipt"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CashLedgerApp"
mc:Ignorable="d"
MinHeight="320" HorizontalAlignment="Stretch">
<UserControl.Resources>
<CollectionViewSource x:Key="AccountsList" Source="{Binding Path=Accounts, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl.Resources>
<Border Margin="100,20" BorderBrush="gray" BorderThickness="0.5">
<Grid Background="White">
<DataGrid x:Name="clDatagrid" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="8" Margin="10,0" VerticalAlignment="Stretch" MinHeight="30" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="False" CanUserAddRows="True">
<DataGrid.Resources>
<Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="0,0,1,0"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Compte No" Width="1*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource AccountsList}}"
SelectedItem="{Binding account}"
DisplayMemberPath="account"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Description" Width="3*" Binding="{Binding description}"/>
<DataGridTextColumn Header="Montant" Width="1.5*" Binding="{Binding amount}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Border>
</UserControl>
I might have missed something I think but can't figure out what.
Binding {Binding Path=accounts} will work if you make accounts a public property (currently it is a private field)
public ObservableCollection<string> accounts { get; private set; }
also naming conventions suggest it should become Accounts (and {Binding Path=Accounts})
additionally simple Binding searches properties in DataContext, but in your case Accounts is a property of UserControl itself, so it is necessary to change source of Binding:
<CollectionViewSource x:Key="AccountsList"
Source="{Binding Path=Accounts, RelativeSource={RelativeSource AncestorType=UserControl}}"/>

Why changing DataGrid ComboBox value does not update the bound property at all?

I have DataGridComboBoxColumn that is supposed to show integers or text "Default". When I add row the combobox gets correct value from viewmodel's bound property, but when I change value in user interface, the property's set is not called. I tried both SelectedValueBinding and SelectedItemBinding. Converter's ConvertBack is never called. I don't event know should it be called.
Things that work:
DataGrid SelectedItem binding
Text column binding both ways (omitted here for shortness)
Here is my code:
XAML:
<DataGrid Name="SelectionSetsGrid" CanUserAddRows="False" CanUserResizeColumns="True" CanUserSortColumns="True"
ItemsSource="{Binding SelectionSets}" AutoGenerateColumns="False"
SelectedItem="{Binding SelectedSelectionSet}">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Width" SelectedValueBinding="{Binding LineWidthIndex}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
ViewModel (ViewModel implements INotifyPropertyChanged and SetValue raises PropertyChanged):
public class SelectedObjectsViewModel : ViewModel
{
private int[] _lineWidths = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
public ObservableCollection<int> LineWidths { get; private set; };
private ObservableCollection<SelectionSetViewModel> _selectionSets;
public ObservableCollection<SelectionSetViewModel> SelectionSets
{
get { return _selectionSets; }
set { this.SetValue(ref _selectionSets, value); }
}
private SelectionSetViewModel _selectedSelectionSet;
public SelectionSetViewModel SelectedSelectionSet
{
get { return this._selectedSelectionSet; }
set { this.SetValue(ref _selectedSelectionSet, value); }
}
}
ViewModel for DataGrid row (ViewModel implements INotifyPropertyChanged and SetValue raises PropertyChanged):
public class SelectionSetViewModel : ViewModel
{
public SelectionSetViewModel()
{
LineWidthIndex = -1;
}
private int _lineWidthIndex;
public int LineWidthIndex
{
get { return _lineWidthIndex; }
set { SetValue(ref _lineWidthIndex, value); }
}
Converter:
public class IntToIntTextOrDefaultConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if ((int)value == -1)
return Fusion.App.Current.Resources["StrDefault"].ToString();
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
}
It seems that on some occasions like after editing the text column and pressing enter or adding new row the property WAS actually updated (set called) after changing combobox value. So I just added UpdateSourceTrigger=PropertyChanged to binding and the update to source property happened immediately (and not after some random operation). Note that changing focus from ComboBox was not enough to update source property so I thought it was never updated.
<DataGrid Name="SelectionSetsGrid" CanUserAddRows="False" CanUserResizeColumns="True" CanUserSortColumns="True"
ItemsSource="{Binding SelectionSets}" AutoGenerateColumns="False"
SelectedItem="{Binding SelectedSelectionSet}">
<DataGridComboBoxColumn Header="{StaticResource XpStrTopologyWidth}" SelectedItemBinding="{Binding LineWidthIndex, UpdateSourceTrigger=PropertyChanged}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox" BasedOn="{StaticResource Theme.ComboBox.Style}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.LineWidths}"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Converter={StaticResource IntToIntTextOrDefaultConverter}}" VerticalAlignment="Center"/>
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>

ListViewItem change text color using index

I want to create a playlist.
But I have a problem to highlight the selected item indicated by the user and change the background color or the color of the text item that is played now.
Properties i want to show - what is play now (int IndexToPlay) what user selects (SelectedIndex)
The user should select only one item
I use WPF, MVVM, and I read a lot of posts, but unfortunately I have not found a solution.
<ListView Name="List"
Grid.ColumnSpan="11" Margin="7,0,7,0.4" Grid.Row="9"
ItemsSource="{Binding MusicList, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedIndex}"
>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
If you have IsSelected and IsPlaying properties in your ViewModel class:
public class MusicItem
{
private bool _isPlaying;
public bool IsPlaying
{
get
{
return _isPlaying;
}
set
{
_isPlaying = value;
OnPropertyChanged();
}
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged();
}
}
}
You can set the ItemContainerStyle to bind the IsSelected property and then you can use a style on the ItemTemplate with a DataTrigger to change the appearance of the ItemTemplate:
<ListView Name="List"
ItemsSource="{Binding MusicList, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedIndex}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPlaying}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Combobox-Datatemplate & Selection TextBox

I have a combobox which has 2 items. Each item is an objet deriving from a common interface. There is a DisplayText property on each object. Each object is templated so as to have a different visual. Everything works fine, except while selecting one of those objects, the visual is getting displayed in the combobox textbox. I want it to display the SelectedText property of the selected object in the textbox and the DisplayText inside the item template. How do I specify my binding for that please?
Here is my code:
public interface IMyDate
{
string DisplayText { get; }
string SelectedText { get; }
}
public class TodayMinus1 : IMyDate
{
public string DisplayText { get { return "Yesterday"; } }
public string SelectedText{get { return DateTime.Today.AddDays(-1).ToString(); }}
}
public class Today : IMyDate
{
public string DisplayText { get { return "TODAY"; } }
public string SelectedText { get { return DateTime.Today.ToString(); } }
}
public class MyMainViewModel
{
public MyMainViewModel()
{
MyDates = new List<IMyDate>() {new Today(), new TodayMinus1()};
}
public List<IMyDate> MyDates { get; set; }
public IMyDate SelectedDate { get; set; }
}
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}" SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock Text="{Binding DisplayText}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock Text="{Binding DisplayText}"/>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
Please note that this is an oversimplified example and I have implemented INPC for all my objects.
Try this:
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}"
SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding DisplayText}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding SelectedText}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding DisplayText}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="{x:Null}">
<Setter Property="Text" Value="{Binding SelectedText}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
Added a DataTrigger inside the DataTemplate to achieve your requirement. Try this.
<ComboBox MaxHeight="26" VerticalAlignment="Center" x:Name="contextDropdown" ItemsSource="{Binding MyDates}" SelectedItem="{Binding SelectedDate}" Grid.Column="1" Width="150" Margin="5">
<ComboBox.Resources>
<DataTemplate DataType="{x:Type local:TodayMinus1}">
<TextBlock Text="{Binding DisplayText}" x:Name="DisplayBox"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}" Value="{x:Null}">
<Setter TargetName="DisplayBox" Property="Text" Value="{Binding SelectedText}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Today}">
<TextBlock Text="{Binding DisplayText}" x:Name="DisplayBox"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}" Value="{x:Null}">
<Setter TargetName="DisplayBox" Property="Text" Value="{Binding SelectedText}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>

Categories