I have the following datagrid:
<DataGrid ItemsSource="{Binding PluginItems}" DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}" x:Name="dtg_Plugins" HorizontalAlignment="Left" VerticalAlignment="Top" Height="315" Width="446" CanUserAddRows="False" AutoGenerateColumns="False" SelectionMode="Single" Padding="0" RowHeight="26">
And it contains column:
<DataGridTemplateColumn CanUserResize="False" CanUserReorder="False" Width="26">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btn_PluginPlay" Padding="0" Height="26" Style="{StaticResource MetroFlatButton}" Background="Transparent" VerticalContentAlignment="Top" HorizontalContentAlignment="Left" Click="btn_PluginPlay_Click">
<Image Width="26" Height="26">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource PlayIcon}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Source" Value="{StaticResource PlayIcon}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsRunning, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="Source" Value="{StaticResource StopIcon}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I'm not sure why but the DataTrigger to change the image as shown, doesn't work.
The ItemsSource is ObservableCollection, the rest works just fine.
What could be the cause for this?
You only need a single DataTrigger:
<Button x:Name="btn_PluginPlay" Padding="0" Height="26" Style="{StaticResource MetroFlatButton}"
Background="Transparent" VerticalContentAlignment="Top" HorizontalContentAlignment="Left"
Click="btn_PluginPlay_Click">
<Image Width="26" Height="26">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource PlayIcon}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="Source" Value="{StaticResource StopIcon}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
Then it should work provided that the PluginItem class, or whatever you call it, has a public bool property called IsRunning that raises change notifications whenever it's set to a new value.
Related
I've got a DataTemplate which looks like this
<DataTemplate DataType="{x:Type viewModel:TreeViewLeafViewModel}">
<StackPanel Orientation="Horizontal">
<Image Name="leafImage"/>
<TextBlock Name="leafTextBlockDisplayName" VerticalAlignment="Center"/>
<TextBlock Name="leafTextBlockKeyGesture" VerticalAlignment="Center"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Row, Converter={StaticResource MatchTypeConverter},
ConverterParameter={x:Type viewModel:TreeViewLeafViewModel}}" Value="True">
<Setter Property="Source" TargetName="leafImage" Value="{Binding Path=Row.Icon, Mode=OneTime}" />
<Setter Property="Text" TargetName="leafTextBlockDisplayName" Value="{Binding Path=Row.DisplayName, Mode=OneTime}" />
<Setter Property="Text" TargetName="leafTextBlockKeyGesture" Value="{Binding Path=Row.KeyGesture.KeyModifierString, Mode=OneTime}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
I would like to replace the leafTextBlockKeyGesture by a TextBox if the IsEditing flag of the corresponding viewmodel is set to true. My Idea was to use a ContentControl inside the DataTemplate and change its Content depending on the IsEditing flag. I tried several solutions but I cannot find a working one.
Does anyone know how to do this?
Based on this answer you need something like this:
<StackPanel>
<StackPanel.Resources>
<DataTemplate x:Key="textbox">
<TextBox Text="edit me"/>
</DataTemplate>
<DataTemplate x:Key="textblock">
<TextBlock Text="can't edit"/>
</DataTemplate>
</StackPanel.Resources>
<CheckBox IsChecked="{Binding IsEditable}" Content="Editable"/>
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource textblock}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditable}" Value="true">
<Setter Property="ContentTemplate" Value="{StaticResource textbox}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</StackPanel>
I have the following Xaml code and I have label triggers. I want to have a trigger that will place an image in the background for some content value. How do i do this as a trigger?
<Window.Resources>
<DataTemplate x:Key="DataTemplate_Level2">
<Label Content="{Binding }" Width="70" Height="70" HorizontalContentAlignment="Center" x:Name="Background">
</Label>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="1">
<Setter TargetName="Background" Property="Background" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="5">
<Setter TargetName="Background" Property="Background" Value="Image"/>
</DataTrigger>
<DataTrigger Binding="{Binding }" Value="9">
<Setter TargetName="Background" Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="7">
<Setter TargetName="Background" Property="Background" Value="blue"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<DataTemplate x:Key="DataTemplate_Level1">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
</Window.Resources>
Simply use ImageBrush as background.
First add the brush in the resources.
Example:
<Window.Resources>
<ImageBrush x:Key="MyImageBrush"
ImageSource="C:\Test.png" />
</Window.Resources>
Then simply use StaticResource to set it in the specific trigger.
<DataTemplate x:Key="DataTemplate_Level2">
<Label Content="{Binding }"
Width="70"
Height="70"
HorizontalContentAlignment="Center"
x:Name="Background">
</Label>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}"
Value="7">
<Setter TargetName="Background"
Property="Background"
Value="{StaticResource MyImageBrush}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
How do you conditionally style treeviewitemson binded properties
I'm running into an issue where I want to style items in a Tree View, those that are valid selections vs hierarchy items.
I've tried to move my style tag into a TreeView.Resources and a TreeView.ItemContainerStyle tag but it still doesn't cause any formatting.
<TabItem Name="Queries" Header="Queries"
d:DataContext="{d:DesignInstance views:QuerySettingsView}">
<Grid>
<TreeView ItemsSource="{Binding QueryTreeModels}"
Width="500" Height="200" VerticalAlignment="Top"
HorizontalAlignment="Center" Margin="0,0,175,0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style >
<Setter Property="TreeViewItem.IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="TreeViewItem.IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsQuery}">
<Setter Property="TextBlock.Foreground" Value="Chartreuse" />
</DataTrigger>
<DataTrigger Binding="{Binding IsFolder}">
<Setter Property="TextBlock.Foreground" Value="Crimson" />
</DataTrigger>
</Style.Triggers>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</TabItem>
For DataTrigger you need to complete the condition by adding a value to DataTrigger bound field. like <DataTrigger Binding="{Binding IsQuery}" Value="true"> Refer the below code.
<TreeView x:Name="tree" Width="500" Height="200"
VerticalAlignment="Top" HorizontalAlignment="Center"
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style >
<Setter Property="TreeViewItem.IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="TreeViewItem.IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsQuery}" Value="true">
<Setter Property="TreeViewItem.Foreground" Value="Chartreuse" />
</DataTrigger>
<DataTrigger Binding="{Binding IsFolder}" Value="true">
<Setter Property="TreeViewItem.Foreground" Value="Crimson" />
</DataTrigger>
</Style.Triggers>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding NodeName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I'm trying to display a "No record found" Message in my WPF Datagrid
I tried the solution from the same question here:
Show "No record found" message on a WPF DataGrid when it's empty
But so far I didn't find a way to add a empty line only when my ObservableCollection is empty.
This is the code for my datagrid:
<DataGrid
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
ItemsSource="{Binding CameraListObjCode}"
AutoGenerateColumns="False"
Height="145"
HorizontalAlignment="Left"
Margin="62,105,0,0"
Name="dataGrid1"
VerticalAlignment="Top"
Width="361"
IsReadOnly="True">
<DataGrid.Resources>
<conv:IntIsEqualOrGreaterThan x:Key="intIsEqualOrGreaterThan"/>
<conv:IntIsLessThan x:Key="intIsLessThan"/>
<Style TargetType="DataGrid">
<Setter Property="RowDetailsVisibilityMode" Value="Collapsed"></Setter>
<Style.Triggers>
<!--<DataTrigger Binding="{Binding Path=CameraListObjCode.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource intIsEqualOrGreaterThan}, ConverterParameter=1}" Value="True">-->
<DataTrigger Binding="{Binding Path=CameraListObjCode.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource intIsLessThan}, ConverterParameter=1}" Value="True">
<Setter Property="RowHeight" Value="0"></Setter>
<Setter Property="RowDetailsVisibilityMode" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Camera Model:" Binding="{Binding CameraModel}" />
<DataGridTextColumn Header="Serial Nr:" Binding="{Binding SerialNr}" />
<DataGridTextColumn Header="IP Address:" Binding="{Binding IPAddress}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="No Record Found" Visibility="Visible" />
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
The Triggers all work as as expected. But the message is not displayed.
When I change the Trigger Converter from "intIsLessThan" to "intIsEqualOrGreaterThan" the Message is shown instead of the actual datagrid entry.
So I guess just the empty default row is missing. But how can I add an empty default row?
I hope anyone can help me with this problem.
I'm already searching for two days now to find a solution...
i use this in my project:
<Style x:Key="{x:Type ItemsControl}" TargetType="{x:Type ItemsControl}">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="No record found"
FontFamily="{StaticResource FontFamily}"
FontSize="{StaticResource FontSize}"/>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Items, RelativeSource={RelativeSource Self}}" Value="{x:Null}">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="No record found"
FontFamily="{StaticResource FontFamily}"
FontSize="{StaticResource FontSize}"/>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}" BasedOn="{StaticResource {x:Type ItemsControl}}">
</Style>
I am having following DataGrid Code
<UserControl x:Class="abc.WPFApp.UCGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPFtoolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:abc.WPFApp">
<UserControl.Resources>
<!--Restrict editing based on IsVariable-->
<Style x:Key="CheckBoxCellStyle" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsVariable}" Value="true">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</UserControl.Resources>
<Grid>
<WPFtoolkit:DataGrid x:Name="UCdataGridView" ItemsSource="{Binding}"
CellStyle="{StaticResource defaultCellStyle}"
RowStyle="{StaticResource defaultRowStyle}"
ColumnHeaderStyle="{StaticResource defaultDataGridColumnHeader}"
SelectionUnit="FullRow"
IsSynchronizedWithCurrentItem="True"
RowBackground="White"
AlternatingRowBackground="AliceBlue"
AutoGenerateColumns="False" SelectionMode="Extended" RowHeaderWidth="20"
CanUserAddRows="True" CanUserDeleteRows="True" CanUserReorderColumns="False"
CanUserResizeColumns="True" AllowDrop="True" KeyUp="UCGridKeyUp" >
<WPFtoolkit:DataGrid.Columns>
<WPFtoolkit:DataGridCheckBoxColumn x:Name="dgChkRepeatingData" Binding="{Binding Path=MasterDataFlag}" MaxWidth="135" MinWidth="80"
Header="Repeating data" Visibility="Collapsed" IsReadOnly="{Binding (IsVariable)}"
EditingElementStyle="{StaticResource CheckBoxCellStyle}"
>
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridCheckBoxColumn MaxWidth="100" Header="Max Element" x:Name="dgChkMaxElement"
Binding="{Binding Path=MaxElement}" MinWidth="70" Visibility="Collapsed"
EditingElementStyle="{StaticResource CheckBoxCellStyle}">
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridCheckBoxColumn MaxWidth="100" Header="In For Loop" x:Name="dgChkInForLoop"
Binding="{Binding Path=InForLoop}" MinWidth="70" Visibility="Collapsed"
EditingElementStyle="{StaticResource CheckBoxCellStyle}">
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridTextColumn x:Name="dgXPath" Binding="{Binding Path=XPath}" Header="XPath" Width="500"
Visibility="Collapsed" IsReadOnly="{Binding Path=IsVariable}"
EditingElementStyle="{StaticResource TextBoxCellStyle}"/>
</WPFtoolkit:DataGrid.Columns>
</WPFtoolkit:DataGrid>
This user control Grid comprised if three Columns which should be mutually exclusive.
I want to achieve this by creating Triggers in XAML itself , How can we do this ?
You can use radiobuttons with a checkbox style to achieve mutually exclusive behavior. If you have any problem binding radiobuttons: radiobutton-binding
<RadioButton IsChecked="{Binding VMProperty}" GroupName="IsSelectedGroup">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=RadioButton}}" Content="{TemplateBinding Content}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
But, i agree with Jaster. If you have each row binded to a ViewModel, the place to put this logic restriction is the ViewModel.
i am trying by creating such Style for 3rd column "InFor" But it is not at all working
<Style x:Key="mutualCheckInForLoop" TargetType="{x:Type WPFtoolkit:DataGridCell}" BasedOn="{StaticResource {x:Type WPFtoolkit:DataGridCell}}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=dgChkRepeatingData,Path=IsChecked}" Value="True">
<Setter Property="CheckBox.IsChecked" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=dgChkMaxElement,Path=IsChecked}" Value="True">
<Setter Property="CheckBox.IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>