I have a TreeView intended to operate on two levels. For his I have two HierarchicalDataTemplate and two custom types. The ItemsSource is linked to a ObservableCollection and everything works fine. I just can't figure how to make a node selected or expanded from codebehind. Somewhere was mentioned a very good idea of binding IsExpanded and IsSelected properties to the corresponding properties in my custom types. The only problem is that the HierarchicalDataTemplate does not implement a TreeViewItem directly, so how can I access these properties in the following code?
<TreeView Name="treeViewNotes" AllowDrop="True" PreviewMouseLeftButtonDown="treeViewNotes_PreviewMouseLeftButtonDown" PreviewMouseMove="treeViewNotes_PreviewMouseMove" Drop="treeViewNotes_Drop" DragEnter="treeViewNotes_DragEnter">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type dataclasses:NoteFolder}" ItemsSource="{Binding Notes}">
<StackPanel Orientation="Horizontal">
<Image Height="16" Source="{Binding TreeViewIcon}" Tag="{Binding Self}"/>
<TextBlock Text="{Binding Title}" Tag="{Binding Self}" Margin="3"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type dataclasses:Note}">
<StackPanel Orientation="Horizontal">
<Image Height="16" Source="{Binding TreeViewIcon}" Tag="{Binding Self}"/>
<TextBlock Text="{Binding Title}" Tag="{Binding Self}" Margin="3"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
My goal is when creating and adding a new Note to some NoteFolder, to make this Note selected and the Folder expanded. The same would be needed to further improve the UI response on drag&drop.
You could try changing the TreeView's ItemContainerStyle in the following way, so that its IsExpanded and IsSelected properties would bind to the DataContext's IsExpanded and IsSelected:
<TreeView x:Name="..." ItemsSource="{Binding RootNode}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<!-- Items in the ItemsSource need to have these properties for the binding to work -->
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!-- You can also optionally change some style values based on IsSelected and IsExpanded values -->
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="BorderThickness" Value="4 0 0 1"/>
<Setter Property="BorderBrush" Value="DeepSkyBlue"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected}" Value="False">
<Setter Property="BorderThickness" Value="4 0 0 1 "/>
<Setter Property="BorderBrush" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate>
...
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Of course, then each item coming from the ItemSource and present in the hierarchy needs to have these properties.
The only problem is that the HierarchicalDataTemplate does not
implement a TreeViewItem directly, so how can I access these
properties in the following code?
You can do that in TreeView.ItemContainerStyle:
<TreeView ItemTemplate="{StaticResource ResourceKey=treeViewDataTemplate}"
ItemsSource="{Binding Data}"
Name="trvTreeView">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}" />
<EventSetter Event="Expanded" Handler="TreeViewItem_Expanded" />
<EventSetter Event="Collapsed" Handler="TreeViewItem_Collapsed" />
<EventSetter Event="PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
In the code behind:
private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
{
TreeViewItem treeViewItem = e.OriginalSource as TreeViewItem;
if (treeViewItem != null)
{
BaseObjectExplorerNode baseObjectExplorerNode = treeViewItem.Header as BaseObjectExplorerNode;
if (baseObjectExplorerNode != null)
{
baseObjectExplorerNode.IsExpanded = true;
}
}
}
private void TreeViewItem_Collapsed(object sender, RoutedEventArgs e)
{
TreeViewItem treeViewItem = e.OriginalSource as TreeViewItem;
if (treeViewItem != null)
{
BaseObjectExplorerNode baseObjectExplorerNode = treeViewItem.Header as BaseObjectExplorerNode;
if (baseObjectExplorerNode != null)
{
baseObjectExplorerNode.IsExpanded = false;
}
}
}
And then for example:
root.IsExpanded = true;
I don't see any problem. You can make a StyleSelector, two Style's and bind to properties.
XAML:
<TreeView Name="treeViewNotes" AllowDrop="True" PreviewMouseLeftButtonDown="treeViewNotes_PreviewMouseLeftButtonDown" PreviewMouseMove="treeViewNotes_PreviewMouseMove" Drop="treeViewNotes_Drop" DragEnter="treeViewNotes_DragEnter">
<TreeView.Resources>
<!-- StyleSelector for containers -->
<notdataclasses:NoteStyleSelector x:Key="NoteStyleSelector" />
<!-- Style for a NoteFolder's container -->
<Style x:Key="NoteFolderStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}" />
<Setter Property="ItemContainerStyleSelector" Value="{StaticResource NoteFolderStyle}" />
</Style>
<!-- Style for a Note's container -->
<Style x:Key="NoteStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
</Style>
<!-- ... -->
</TreeView.Resources>
<TreeView.ItemContainerStyleSelector>
<StaticResource ResourceKey="NoteStyleSelector" />
</TreeView.ItemContainerStyleSelector>
</TreeView>
NoteStyleSelector:
public sealed class NoteStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
FrameworkElement fe = container as FrameworkElement;
if (fe!= null)
{
if (item is Note)
{ return (Style)fe.FindResource("NoteStyle"); }
if (item is NoteFolder)
{ return (Style)fe.FindResource("NoteFolderStyle"); }
}
return base.SelectStyle(item, container);
}
}
In a drop handler:
currentFolder.Nodes.Add(pastedNode);
currentFolder.IsExpanded = true;
currentNode.IsSelected = true;
Data casses:
public class Note : INotifyPropertyChanged
{
// Only the IsSelected property because a Note can not be expanded
public bool IsSelected { get { /* ... */ } set { /* ... */ } }
}
public class NoteFolder : INotifyPropertyChanged
{
public bool IsSelected { get { /* ... */ } set { /* ... */ } }
public bool IsExpanded { get { /* ... */ } set { /* ... */ } }
}
Related
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.
I have a problem with a dynamic ContextMenu on a Button.
The Button is inside a DataGrid with the following Columndefinition in a ResourceDictionary:
<DataGridTemplateColumn Width="16" x:Key="ShowContextMenuColumn" x:Shared="False" KeyboardNavigation.IsTabStop="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Style="{StaticResource ShowContextMenuButtonStyle}">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding Data.ContextActionItems, Source={StaticResource proxy}}" DisplayMemberPath="DisplayText">
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon">
<Setter.Value>
<Image Source="{Binding Image}"/>
</Setter.Value>
</Setter>
<Setter Property="Command" Value="{Binding Command}"/>
</Style>
</ContextMenu.Resources>
</ContextMenu>
</Button.ContextMenu>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{markup:Type DataGridCell}" BasedOn="{StaticResource BaseDataGridCellStyle}">
<Setter Property="AutomationProperties.Name" Value="ContextMenu"/>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
The ObservableCollection<DisplayListActionItem> for the ContextActionItems is defined in an abstract generic base-class which is inherited by several ViewModels.
The DisplayListActionItem-Class looks like:
public class DisplayListActionItem : NotifyBase
{
public string DisplayText
{
get { return Get<string>(); }
set { Set(value); }
}
public ICommand Command
{
get { return Get<ICommand>(); }
set { Set(value); }
}
public ImageSource Image
{
get { return Get<ImageSource>(); }
set { Set(value); }
}
}
Everything just works fine. The only problem is, that the Image is only shown at the last item of the ContextMenu. If I remove the last item, then the image of the new last item is shown. I don't understand what's the reason for this.
I've already checked the Debug-Output for Binding-Errors, but there are none.
Any ideas what could cause this problem?
Solved it by myself.
The solution was to modify the ContextMenu-ItemContainerStyle instead doing the needed stuff in the Resources of the ContextMenu.
The new xaml for the Button looks like:
<Button Style="{StaticResource ShowContextMenuButtonStyle}">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding Data.ContextActionItems, Source={StaticResource proxy}}" >
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Icon" Value="{Binding Image, Converter={converter:ImageSourceToImageConverter}}"/>
<Setter Property="Header" Value="{Binding DisplayText}"/>
<Setter Property="Command" Value="{Binding Command}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
</Button>
I am using WPF Datagrid to group an observable collection by Parent. I have been following the example here and other examples showing a parent child relationship. So far I have the following:
And I want to get something like this:
Where the Header of a group is just a row as well but still able to collapse/expand child rows. I have tried to make a sub-datagrid without luck. So the underlying type of my collection looks something like this:
public class Task : INotifyPropertyChanged, IEditableObject
{
// memebers
...
public string ProjectName
{
get { return this.m_ProjectName; }
set
{
if (value != this.m_ProjectName)
{
this.m_ProjectName = value;
NotifyPropertyChanged("ProjectName");
}
}
}
public string TaskName
{
get { return this.m_TaskName; }
set
{
if (value != this.m_TaskName)
{
this.m_TaskName = value;
NotifyPropertyChanged("TaskName");
}
}
}
public DateTime DueDate
{
get { return this.m_DueDate; }
set
{
if (value != this.m_DueDate)
{
this.m_DueDate = value;
NotifyPropertyChanged("DueDate");
}
}
}
public bool Complete
{
get { return this.m_Complete; }
set
{
if (value != this.m_Complete)
{
this.m_Complete = value;
NotifyPropertyChanged("Complete");
}
}
}
public Task Parent
{
get { return m_Parent; }
set
{
m_Parent = value;
}
}
So my object type can either by a child or parent, where a child has a reference to its parent. So I am grouping by parent, I just haven't figured out how to make the expandable group headers rows of the same type. Any help is appreciated.
Here is the xaml:
<DataGrid x:Name="dataGrid1"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False"
ColumnWidth="*"
RowHeaderWidth="0">
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE" BorderThickness="1,1,1,5">
<Expander.Header>
<DockPanel HorizontalAlignment="Stretch" >
<TextBlock FontWeight="Bold" Text="{Binding Path=Name, Converter={StaticResource completeConverter}}" Margin="5,0,0,0" Width="200" HorizontalAlignment="Stretch"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount}" Width="Auto"/>
</DockPanel>
<!--<DataGrid x:Name="dataGrid2"
ItemsSource="{Binding Source={StaticResource vsParentTasks}}"
CanUserAddRows="False"
ColumnWidth="*"
RowHeaderWidth="0"
HeadersVisibility="None" >
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Foreground" Value="#FFEEEEEE" />
<Setter Property="Background" Value="#FF112255" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</DataGrid.RowStyle>
</DataGrid>-->
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="White" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
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>
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>