How to get this binding for item instead of TreeViewItem? - c#

I got the following code :
<HierarchicalDataTemplate x:Key="AssignedRate" ItemsSource="{Binding Children}" DataType="{x:Type local:UnitRateCatElement}">
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<StackPanel Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Text="{Binding Category.Description}" />
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Unit Rate"
Command="{Binding Path=PlacementTarget.Tag.AddUnitRateCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</ControlTemplate>
</ContentControl.Template>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="Hello, it works!" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</HierarchicalDataTemplate>
The binding in the line : <DataTrigger Binding="{Binding Path=IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}" Value="True">
is incorrect (VS says so). How can I get this to work? The class local:UnitRateCatElement does have a IsDefined property. But I cannot get the binding right to point to that object. How can I get this binding right?

Try
Binding="{Binding Path=DataContext.IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"

I think you should be doing this -
<DataTrigger Binding="{Binding Path=DataContext.IsDefined,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type TreeViewItem}}}" Value="True">
as your RelativeSource binding points to the TreeViewItem, which doesn't have IsDefined property, it is present in the DataContext of the TreeViewItem.
Update:
For your second problem (trigger not working), this is happening because you are setting the Template explicitly i.e. Local Value which is having higher precedence then Triggers; this should work -
<ControlTemplate x:Key="DefaultTemplate">
<StackPanel Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Text="{Binding Category.Description}" />
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Unit Rate"
Command="{Binding Path=PlacementTarget.Tag.AddUnitRateCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</ControlTemplate>
<ControlTemplate x:Key="DefinedTemplate">
<TextBlock Text="Hello, it works!" />
</ControlTemplate>
<HierarchicalDataTemplate x:Key="AssignedRate" ItemsSource="{Binding Children}"
DataType="{x:Type local:UnitRateCatElement}">
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template" Value={StaticResource DefaultTemplate}>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.IsDefined, RelativeSource=
{RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"
Value="True">
<Setter Property="Template" Value={StaticResource DefinedTemplate}>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</HierarchicalDataTemplate>

Related

How to change the display data format of the WPF DatePicker

I got this sample code from this forum.
<DatePicker SelectedDate="{Binding MainReportEndDate, Mode=TwoWay}"
DataContext="{Binding DataContext, RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}"
DisplayDateStart="1/01/20" DisplayDateEnd="12/31/22"
FirstDayOfWeek="Monday"">
<DatePicker.Resources>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox"
Text="{Binding Path=SelectedDate,
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}},
StringFormat={}{0:MMM yy}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
</DatePicker>
But it doesn't work. I want the same result as the one in the picture "Jul 20"
Try this
<TextBox x:Name="PART_TextBox"
Text="{Binding Path=SelectedDate, StringFormat='dd MMM yyyy',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />

Trigger to set Property in ItemTemplate

I have the following definition of a UserControl
<UserControl x:Class="Logger.View.AdvancedToggleButton"
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:converter="clr-namespace:Logger.Converter"
xmlns:commonControls="clr-namespace:Logger.CommonControls"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<UserControl.Resources>
<converter:CountToVisibilityConverter x:Key="CountToVisibilityConverter" />
</UserControl.Resources>
<ItemsControl ItemsSource="{Binding LogElements, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<Style TargetType="{x:Type ToggleButton}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="container"
BorderThickness="1" Margin="1,2,1,1" Padding="2,2,4,2" BorderBrush="Black">
<ContentPresenter x:Name="contentPresenter" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="container" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<Setter Property="BorderThickness" TargetName="container" Value="1,1,1,0"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" TargetName="container" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
<Setter Property="Background" Value="{Binding SelectionBrush, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ToggleButton Margin="2,1"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Command="{Binding DataContext.ToggleCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
CommandParameter="{Binding}">
<ToggleButton.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0" x:Name="tbText"/>
<Border Grid.Column="1" Margin="0,-1,-3,-1" MinWidth="20"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Background="Yellow" BorderBrush="LightGray" BorderThickness="1,0,0,0"
Visibility="{Binding WarningCount, Converter={StaticResource CountToVisibilityConverter}}"
Cursor="Hand">
<commonControls:ActionLink HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding WarningCount}"
FontFamily="Consolas" Margin="2,0" Command="{Binding DataContext.NavigateToWarningCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
</Border>
<Border Grid.Column="2" Margin="3,-1,-3,-1" MinWidth="20"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Background="Red" BorderBrush="LightGray" BorderThickness="1,0,0,0"
Visibility="{Binding ErrorCount, Converter={StaticResource CountToVisibilityConverter}}"
Cursor="Hand" >
<commonControls:ActionLink HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ErrorCount}"
FontFamily="Consolas" Foreground="White" Margin="2,0" />
</Border>
</Grid>
</ToggleButton.Content>
</ToggleButton>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
Everything just works fine. Now I've added another Property to this UserControl to set the BackgroundColor of the Checked ToggleButton-TextBlock (tbText) to a given SolidColorBrush.
My problem now is, that I have no idea how to correctly set the Trigger for this.
I tried to add the Trigger to the ControlTemplate.Triggers when the IsChecked is True. But I don't know how to access tbText from this point. Is this the correct location for the Trigger or do I have to add another Trigger at a lower level?
Your ToggleButton.IsChecked property is data bound to your IsSelected property so by default, you also want to set the TextBlock.Background when this IsSelected property is true. You can do that like this:
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0"
x:Name="tbText">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="{Binding YourColourBrush,
RelativeSource={RelativeSource AncestorType={x:Type
YourPrefix:YourUserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
Alternatively, you could just data bind directly to the ToggleButton.IsChecked property like this:
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="4,0,5,0"
x:Name="tbText">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource
AncestorType={x:Type ToggleButton}}}" Value="True">
<Setter Property="Background" Value="{Binding YourColourBrush,
RelativeSource={RelativeSource AncestorType={x:Type
YourPrefix:YourUserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

Binding Contextmenu

<ItemsControl ItemsSource="{Binding ViewModelOne.Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate >
<ContentControl>
<StackPanel Orientation="Vertical">
<StackPanel.ContextMenu>
<ContextMenu >
<MenuItem Header="Delete" Command="{Binding ViewModelOne.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MainWindow}}}" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock x:Name="Details" Text="{Binding Details}" />
<TextBlock x:Name="Name" Text="{Binding Name}" />
<Rectangle x:Name="Rects" Height="10" Width="10" Stroke="Black" StrokeThickness="1" />
</StackPanel>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have the above part of the code in my project and am trying to bind the Contextmenu command, what is the correct way.
I have also tried
<MenuItem Header="Delete" Command="{Binding PlacementTarget.Tag.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" />
Still i couldnot get the command working
Instead of putting ContextMenu on the your StackPanel, set ContextMenu on your Item in ItemContainerStyle and also set the Tag for the Item to the parents DataContext.
<ItemsControl x:Name="MyItemControl" ItemsSource="{Binding ViewModelOne.Items}">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Tag" Value="{Binding DataContext, ElementName=MyItemControl}"></Setter>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu >
<MenuItem Header="Delete" Command="{Binding PlacementTarget.Tag.ViewModelOne.DeleteCommand, RelativeSource={RelativeSource Self}}" />
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>

Stuck on XAML code for TreeView With Checkboxes

I have several treeviews that are populated at the code level.
I want to apply checkboxes to them all with minimal code.
i can see the checkboxes and the items names i used to populate the treeviews with no problem however the treeview isnt expanding.
This is the resource Dictionary. i can see that all the settings are being implemented
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Layout.Toolkit"
xmlns:ToolKit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
x:Name="MainDefaultStyle"
>
<Style TargetType="TreeView">
<Setter Property="Background" Value="White"/>
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualHeight}" />
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}" />
</Style>
<Style TargetType="TreeViewItem" x:Name="TreeViewItem">
<Style.Resources>
<SolidColorBrush Color="AliceBlue" x:Key="{x:Static SystemColors.HighlightBrushKey}"/>
<SolidColorBrush Color="Black" x:Key="{x:Static SystemColors.HighlightTextBrush}"/>
</Style.Resources>
<Setter Property="Background" Value="White" />
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Height" Value="{Binding BindsDirectlyToSource=True}"/>
<Setter Property="Width" Value="{Binding BindsDirectlyToSource=True}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem" >
<StackPanel>
<CheckBox
x:Name="CheckBox1"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Grid.Column="0"
>
<TextBlock
Margin="1"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=Header}"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Foreground="Black"
Grid.Column="1"
Background="AliceBlue">
</TextBlock>
</CheckBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
this is the code in the MainWindow
<TreeView Name="TreeComputers" BorderBrush="Transparent" >
<TreeViewItem Header="This is a test" >
<TreeViewItem Header="Another test"></TreeViewItem>
</TreeViewItem>
</TreeView>
my treeview triggers are created in the code.
TreeComputers.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(TreeView_SelectionChanged);
TreeUsers.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(TreeView_SelectionChanged);
Somehow i need to be able to click the items in the treeview that now have the checkbox on them and trigger the routed command..
any ideas ?
Is your problem that you can no longer expand items in the tree to see the child items?
I think your problems is that you want to set TreeView.ItemTemplate to be a HierarchicalDataTemplate.
Something like:
<Setter Property="ItemTemplate">
<Setter.Value>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel>
<CheckBox
x:Name="CheckBox1"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Grid.Column="0">
<TextBlock
Margin="1"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=Header}"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Foreground="Black"
Grid.Column="1"
Background="AliceBlue">
</TextBlock>
</CheckBox>
</StackPanel>
</HierarchicalDataTemplate >
</Setter.Value>
</Setter>

Binding from DataTrigger

Trying to bind to the Tag property of a textbox from a datatrigger, but doesnt seem to get the binding corrrect
Partial xaml
<TextBox Grid.Column="2" Tag="Enter password" Text="{Binding UserName, Mode=TwoWay}" Name="textBox1" Width="200" Height="25" HorizontalAlignment="Left" >
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type TextBox}},
Path=Tag}"
Foreground="Gray"/>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
Its the part
<TextBlock Text="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type TextBox}},
Path=Tag}"
that is not working. I have tried a couple of solutions, but textbox is always ending up empty.

Categories