In WPF, I'm trying to create a custom data grid that displays a cell as combobox when there is a databound list of data (a range for data), and a normal textbox if there isn't a limit. Additionally, i'm using the included validation for IDataErrorInfo and an MVVM pattern. Most of it works very well, but the devil is in the details. I'm seeing a problem where the validation on my combobox is not working as I expect it to.
I believe the issue I have is when I define both controls using a data trigger, but I'm not sure why it behaves the way it does. If I remove the validation on my textbox, the validation on the combobox works beautifully. When i put the properties back into the textbox to specify validation, the combobox validation no longer works.
Here is my xaml code on how to specify which control to use based on my data trigger:
<UserControl x:Class="GlobalVariableEditor.GlobalVariableEditorUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodel="clr-namespace:GlobalVariableEditor.ViewModel"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:local="clr-namespace:GlobalVariableEditor"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="500" Width="auto" Height="auto">
<UserControl.DataContext>
<viewmodel:GlobalVariableEditorViewModel x:Name="_GVEViewModel"/>
</UserControl.DataContext>
<UserControl.Resources>
<CollectionViewSource x:Key="VariablesViewSource" Source="{Binding VariablesData}">
</CollectionViewSource>
<Style x:Key="RangeStyleNormal" TargetType="ComboBox">
<Setter Property="HorizontalContentAlignment" Value="center"/>
<!--<EventSetter Event="SelectionChanged" Handler="ComboBox_SelectionChanged"></EventSetter>-->
<Setter Property="IsEditable" Value="False" />
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="IsTextSearchCaseSensitive" Value="True"/>
</Style>
</UserControl.Resources>
<GroupBox x:Name="grpGVEditor" Header="Global variable editor" FontSize="12">
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<!--This is for any declarations or headers we may need for initial information (where to load xml file from, etc)-->
<RowDefinition x:Name="TopRowDefinition" Height="*" MinHeight="30" MaxHeight="50" />
<RowDefinition x:Name="RevisionRowDefinition" Height="*" MinHeight="30" MaxHeight="50" />
<!--this is where the data from the xml file should be populated to-->
<RowDefinition x:Name="DataRowDefinition" Height="*" MinHeight="200"/>
<!--this is where the buttons should be placed (cancel, apply, etc)-->
<!--<RowDefinition x:Name="FilterRowDefinition" Height="*" MinHeight ="25" MaxHeight="30"/>-->
<RowDefinition x:Name="ButtonRowDefinition" Height="*" MinHeight ="30" MaxHeight="50" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label Height="30" Width="110" Content="XML file location: " BorderThickness="1" BorderBrush="Black" Margin="3,0,3,0"/>
<Label x:Name="lblCustomXMLFilePath" VerticalContentAlignment="Center" Height="30" Width="350" Content="{Binding FilePath}" BorderThickness="1" BorderBrush="Black" Margin="0,0,3,0" ToolTip="{Binding FilePath}" Background="Gray"/>
<!--<Button x:Name="btnLoad" Height="30" Width="50" Content="Load" Margin="0,5,5,5" Click="btnLoad_Click" Visibility="Hidden"/>-->
<Button Height="30" Width="50" Content="Revert" Margin="0,0,3,0" ToolTip="Revert to TP values" Visibility="Hidden"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Label Name="lblRevID" Height="30" Width="110" Content="File Revision ID: " BorderThickness="1" BorderBrush="Black" Margin="3,0,3,0"/>
<TextBox Name="txtRevID" Padding="3" Height="30" Width="100" VerticalContentAlignment="Center" TextAlignment="Left" BorderThickness="1" BorderBrush="Black" Margin="0,0,3,0" Text="{Binding FileVersion}" IsReadOnly="True" Background="Gray">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding FileVersion}" Value="-1">
<Setter Property="TextBox.Background" Value="Salmon" />
<Setter Property="TextBox.ToolTip" Value="Invalid revision number. Settings file is in read-only mode." />
</DataTrigger>
<DataTrigger Binding="{Binding FileVersion}" Value="0">
<Setter Property="TextBox.Background" Value="Salmon" />
<Setter Property="TextBox.ToolTip" Value="Invalid revision number. Settings file is in read-only mode." />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox x:Name="tbDummy" Visibility="Hidden"></TextBox>
</StackPanel>
<DockPanel Grid.Row="2" HorizontalAlignment="Stretch" MinHeight="200" Margin="0,5,0,0">
<DataGrid x:Name="PropertyGrid" SelectionMode="Single" SelectionUnit="Cell" RowHeaderWidth="0" IsTextSearchCaseSensitive="True" GridLinesVisibility="All"
AutoGenerateColumns="False" AlternationCount="2" ItemsSource="{Binding FilteredGridEntries}" Margin="3,0,0,0">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent"/>
</Style.Resources>
<Setter Property="IsEnabled" Value="{Binding HasWriteAccess}" ></Setter>
<Style.Triggers>
<Trigger Property="AlternationIndex" Value="0">
<Setter Property="Background" Value="White" />
</Trigger>
<Trigger Property="AlternationIndex" Value="1">
<Setter Property="Background" Value="WhiteSmoke" />
</Trigger>
<MultiDataTrigger >
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsReadOnly}" Value="True"/>
<Condition Binding="{Binding IsChecked, ElementName=_cboShowAll}" Value="False"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Visibility" Value="Collapsed"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<DataTrigger Binding="{Binding IsReadOnly}" Value="True">
<Setter Property="Background" Value="Gray"/>
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Resources>
<Style x:Name="CenterContent" TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="{Binding Column.(ToolTipService.ToolTip), RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
<Image x:Name="rowHeaderImage"
x:Key="rowHeaderTemplate"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="64"
Margin="1,0">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReadOnly}" Value="true">
<Setter Property="Source" Value="/Resources/access.ico"/>
</DataTrigger >
<DataTrigger Binding="{Binding IsReadOnly}" Value="false">
<Setter Property="Source" Value="/Resources/no_access.jpg"/>
</DataTrigger >
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataGrid.Resources>
<DataGrid.ItemBindingGroup>
<BindingGroup/>
</DataGrid.ItemBindingGroup>
<DataGrid.Columns>
<!--This is the Name column-->
<DataGridTemplateColumn Header="Name" ToolTipService.ToolTip="Global variable name/ID" MinWidth ="200" Width="2*">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Gray"></Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}" IsReadOnly="True" Background="Transparent" ToolTip="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--This is the Site column-->
<!--<DataGridTemplateColumn Header="Site" ToolTipService.ToolTip="Site" Width="1*" MaxWidth ="30" IsReadOnly="False" Visibility="Hidden">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox TextAlignment="Center" Text="{Binding Site, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" IsReadOnly="{Binding IsReadOnly}" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>-->
<!--This is the Slot column-->
<!--<DataGridTemplateColumn Header="Slot" ToolTipService.ToolTip="Slot" Width="1*" MaxWidth ="30" IsReadOnly="False" Visibility="Hidden">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox TextAlignment="Center" Text="{Binding Slot, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" IsReadOnly="{Binding IsReadOnly}" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>-->
<!--This is the High Limit column-->
<!--<DataGridTemplateColumn Header="High Limit" ToolTipService.ToolTip="High limit" MaxWidth="125" Width="1*" Visibility="Hidden">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox TextAlignment="Center" Text="{Binding HiLimit, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" IsReadOnly="{Binding IsReadOnly}" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>-->
<!--This is the Low Limit column-->
<DataGridTemplateColumn Header="Value" MinWidth="200" ToolTipService.ToolTip="Global variable programmed value" Width="3*">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!--By default, allow the user to free edit the combobox.
This allows backwards compatibility with existing TP settings-->
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding HasRange}" Value="true">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Range, Mode=OneWay}"
MinWidth="50"
Text="{Binding ProgrammedValue,
UpdateSourceTrigger=LostFocus,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}"
Style="{StaticResource RangeStyleNormal}"
Width="auto" >
</ComboBox>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding HasRange}" Value="false">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox
HorizontalAlignment="Stretch"
Background="Transparent"
BorderThickness="0"
MinWidth="50"
Text="{Binding ProgrammedValue, Mode=TwoWay,
UpdateSourceTrigger=LostFocus,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True
}"
TextAlignment="Center"
Width="Auto">
</TextBox>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--This is the Low Limit column-->
<!--<DataGridTemplateColumn Header="Low Limit" ToolTipService.ToolTip="Lower limit" Width="1*" MaxWidth="125" Visibility="Hidden">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox TextAlignment="Center" Text="{Binding LowLimit, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" IsReadOnly="{Binding IsReadOnly}" Background="Transparent"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>-->
<!--This is the Fleet column-->
<DataGridTemplateColumn Header="Fleet Variable" ToolTipService.ToolTip="Global variable scope" MinWidth ="75" Width="1*">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Gray"></Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding IsFleet}" IsReadOnly="True" Background="Transparent" ToolTip="{Binding IsFleet}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--<DataGridCheckBoxColumn Header="Is fleet" Width="1*" MinWidth="50" ToolTipService.ToolTip="Variable of fleet scope" Binding="{Binding IsFleet}" IsReadOnly="True">
</DataGridCheckBoxColumn>-->
</DataGrid.Columns>
</DataGrid>
</DockPanel>
<!--These are the buttons at the bottom of the control-->
<Grid Grid.Row="3">
<StackPanel Height="40" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,2" Width="auto">
<Label Height="25" HorizontalAlignment="Left" Width="40" Margin="5,2,3,0">Filter:</Label>
<TextBox x:Name="_tboFilter" HorizontalAlignment="Left" Height="25" Margin="0,3,0,0" Width="200" MaxLength="40" MaxLines="1" MinLines="1" AcceptsTab="True" TextAlignment="Left" Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Name="_cboShowAll" HorizontalAlignment="Left" Height="25" IsChecked="False" Margin="15,7,0,0">
<TextBlock Text="Show all" />
</CheckBox>
</StackPanel>
<StackPanel Height="40" Width="auto" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,2">
<Button x:Name="btnTestError" HorizontalAlignment="Right" Height="25" Width="60" Content="TestError" ToolTip="Fire error events for logging" Margin="0,0,3,0" Command="{Binding TestErrorButtonCommand}" Visibility="{Binding EnableQADebuggingTools}" />
<!--<Button x:Name="btnApply" Height="25" Width="50" Content="Apply" ToolTip="Apply changes" Margin="0,3,3,0" Click="btnApply_Click" IsEnabled="{Binding HasDataChanged}" />-->
<Button x:Name="btnApply" HorizontalAlignment="Right" Height="25" Width="50" Content="Apply" ToolTip="Apply changes" Margin="0,0,3,0" Command="{Binding ApplyChangesButtonCommand}" >
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<!-- Button enabled if the following conditions is met: HasDataChanged is true -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding HasDataChanged}" Value="True"/>
<Condition Binding="{Binding HasWriteAccess}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<!--<Button x:Name="btnCancel" Height="25" Width="50" Content="Cancel" Margin="0,3,3,0" ToolTip="Revert to TP values" Click="btnCancel_Click" Command="{Binding CancelButtonCommand}"/>-->
<Button x:Name="btnCancel" HorizontalAlignment="Right" Height="25" Width="50" Content="Cancel" Margin="0,0,3,0" ToolTip="Revert to TP values" Click="btnCancel_Click"/>
</StackPanel>
</Grid>
</Grid>
</GroupBox>
</UserControl>
IDataErrorInfo is implemented thusly:
public string this[string columnName]
{
get
{
string result = null;
try
{
if (columnName == "ProgrammedValue")
{
//Validation routine: data can not be empty field.
if (this.HasRange)
{
// This is a combobox
if (ProgrammedValue == null)
{
result = "Field must have selection";
}
else
{
if (Range != null && !Range.Contains(ProgrammedValue) )
{
result = "Field must have selection";
}
}
}
else
{
// This is a text box:
if (string.IsNullOrEmpty(ProgrammedValue))
{
result = "Field can not be empty.";
}
}
}
}
catch (Exception ex)
{
// Eat the exception.. really should never get here, but if there is an exception
result = null;
}
return result;
}
}
In my model, the bound properties are defined:
public string ProgrammedValue
{
get
{
return _programmedValue;
}
set
{
_programmedValue = value;
RaisePropertyChanged("ProgrammedLimit");
}
}
public List<string> Range
{
get
{
return _range;
}
set
{
_range = value;
RaisePropertyChanged("Range");
}
}
public bool HasRange
{
get
{
return _hasRange;
}
set
{
_hasRange = value;
RaisePropertyChanged("HasRange");
}
}
RangeStyleNormal definition:
<UserControl.Resources>
<Style x:Key="RangeStyleNormal" TargetType="ComboBox">
<Setter Property="HorizontalContentAlignment" Value="center"/>
<EventSetter Event="SelectionChanged" Handler="ComboBox_SelectionChanged"></EventSetter>
<Setter Property="IsEditable" Value="False" />
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="IsTextSearchCaseSensitive" Value="True"/>
</Style>
</UserControl.Resources>
As previously stated, when I remove ValidatesOnDataErrors and NotifyOnValidationError from the textbox properties, the combobox works like a charm. I know that the validation routine I have specified works correctly. I'm hoping someone here can see some obvious coding error(s) I've made and explain what I did wrong and how to correct it. Thanks in advance.
It's my GUI.
When I focus on TextBox, I can move focus by Tab key.
But when I focus on Tel No. Text Box, I press Tab Key but focus just stay and not move.
I want to move focus to ComboBox(editable) by pressing Tab key.
.xaml file
<TextBlock Text="{Resx incidentCallName }" Grid.Row="2" Style="{DynamicResource TextBlockSubStyle}"/>
<TextBox x:Name="txtbox_who" Grid.Row="2" Grid.Column="1" Style="{DynamicResource TextInputStyle}" Validation.Error="Validation_Error"
Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=Person, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"/>
<TextBlock Text="{Resx incidentCallNo}" Grid.Row="3" Style="{DynamicResource TextBlockSubStyle}"/>
<TextBox x:Name="txtbox_tel" Grid.Row="3" Grid.Column="1" Style="{DynamicResource TextInputStyle}" LostFocus="txtbox_tel_LostFocus" PreviewKeyDown="txtbox_tel_PreviewKeyDown" Validation.Error="Validation_Error"
Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=Tel, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"/>
<Button x:Name="btn_history" IsTabStop="True" Grid.Row="3" Grid.Column="2" Content="!" Margin="1" IsEnabled="False" Click="btn_history_Click" FontSize="18"/>
<TextBlock Text="{Resx incidentList_type}" Grid.Row="4" Style="{DynamicResource TextBlockSubStyle}"/>
<ComboBox x:Name="cb_type" Grid.Row="4" Grid.Column="1" Style="{DynamicResource ComboBoxStyle}"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=TypeCombo, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Code_name" SelectedValuePath="Comm_code_id" IsEditable="True" IsReadOnly="True" Validation.Error="Validation_Error"
SelectedValue="{Binding UpdateSourceTrigger=PropertyChanged, Path=TypeCode, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"
SelectedIndex="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.CbTypeSelect, UpdateSourceTrigger=PropertyChanged}"/>
App.xaml (for style)
<Style x:Key="ComboBoxStyle" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue"/>
<Style.Triggers>
<Trigger Property="IsSelectionBoxHighlighted" Value="True">
<Setter Property="IsDropDownOpen" Value="true" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsDropDownOpen" Value="true" />
</Trigger>
</Style.Triggers>
</Style>
What is the problem? Please help me.
This should be simple but it is puzzling me. I want to set the Visibility of one of my DataGridTextColumn based on the Visibility of another element. So I did this:
<StackPanel>
<TextBlock Text="This is the text" Name="MyTextBlock" Margin="5">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyTextBox, Path=Text}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBox Text="2" Name="MyTextBox" />
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="H1" />
<DataGridTextColumn Header="H2" Visibility="{Binding ElementName=MyTextBlock, Path=Visibility}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
The Visibility of MyTextBlock works correct but DataGridTextColumn H2 is always visible. What am I doing wrong?
#Ruben solution worked. For anyone that cares here is the working code:
<StackPanel>
<StackPanel.Resources>
<FrameworkElement x:Key="ProxyElement"
DataContext="{Binding ElementName=MyTextBlock}"/>
</StackPanel.Resources>
<TextBlock Text="This is the text" Name="MyTextBlock" Margin="5">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyTextBox, Path=Text}" Value="0">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBox Text="0" Name="MyTextBox" />
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"/>
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="H1" />
<DataGridTextColumn Header="H2" Visibility="{Binding DataContext.Visibility, Source={StaticResource ProxyElement}}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
My styles and resources
<Window.Resources>
<ConvertorObj:BoolToVisibilityConverter x:Key="boolToVis"/>
<Style TargetType="{x:Type TextBlock}" x:Key="GridBlockStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource boolToVis}, ConverterParameter=False}" />
<Setter Property ="FontFamily" Value="Verdana" ></Setter>
<Setter Property ="FontSize" Value="14" ></Setter>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="GridEditStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}},
Converter={StaticResource boolToVis}, ConverterParameter=True}" />
<Style.Triggers>
<DataTrigger>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
These are the two types of styles applied, GridBlockStyle and GridEditStyle. In a normal view the rows should behave like textblocks. When I edit the row it should behave as textbox with a combobox. The problem is that I get comboboxes in all the rows of the listview. it should appear only in certain rows of my listview.
My listview is as follows
<ListView Margin="10" Name="ListValues" AlternationCount="2"
ItemsSource="{Binding Path= ListValues}"
ScrollViewer.VerticalScrollBarVisibility="Auto" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#00B2EE">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="200">
<GridViewColumnHeader Tag="Name" Content="Name" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource GridBlockStyle}" />
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="Auto">
<GridViewColumnHeader Tag="Settings" Content="Settings" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource GridBlockStyle}"
Text="{Binding Path=Settings}"/>
<TextBox Grid.Column="0"
Text="{Binding Path=Settings}"
FontFamily="verdana" FontSize="14"
MaxLength="31" Width="240"
Style="{StaticResource GridEditStyle}"/>
<TextBlock Grid.Column="1" Style="`{StaticResource GridBlockStyle}" />`
<ComboBox Grid.Column="1"
Style="{StaticResource GridEditStyle}"
ItemsSource="{Binding Path=CmbSettings}"
SelectedItem="{Binding Path=CmbSelectType}"
IsEnabled="{Binding Path = IsComboAvailable}"
Grid.RowSpan="2"/>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Sample view model
_sampleModel = new SampleModel();
_sampleModel.Name = "test1";
_sampleModel.Settings = "aa";
_sampleModel.IsComboAvailable = false;
ListValues.Add(_sampleModel);
_sampleModel = new SampleModel();
_sampleModel.Name = "test1";
_sampleModel.Settings = "3";
_sampleModel.CmbSelectType = "Second";
_sampleModel.CmbSettings.Add("Second");
_sampleModel.CmbSettings.Add("Minute");
_sampleModel.IsComboAvailable = true;
ListValues.Add(_sampleModel);
ListValues.Add(_sampleModel);
Currently on editing the row the disabled dropdown is visible. It should be removed.
When IsEnabled is false, a ComboBox will appear grayed out and not be editable. However, since you have located the TextBlock and the ComboxBox in the same grid column, and the ComboBox is declared later, your TextBlock is still covered by the ComboBox even when the ComboBox is disabled. What you want to do is set the Visibility to Collapsed when IsComboAvailable is false.
Try this:
<ComboBox Grid.Column="1" Name="combo"
...
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsComboAvailable}" Value="False">
<Setter TargetName="combo" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
I would like to bind content of contrentcontrol to selectedvalue of combobox and set visibility according to trigger. But it is not work. What is the problem ?
<DockPanel>
<ComboBox x:Name="combobo" Padding="4" Width="120" HorizontalAlignment="Left" Margin="30,10,0,0" VerticalAlignment="Center">
<ComboBoxItem>0</ComboBoxItem>
<ComboBoxItem>1</ComboBoxItem>
</ComboBox>
<ContentControl x:Name="contentcontrol" Grid.Row="0" Grid.Column="2" Content="{Binding ElementName=combobo, Path=SelectedIndex}" Margin="0,10,0,0" VerticalAlignment="Center"
Visibility="Visible">
<ContentControl.ContentTemplate>
<DataTemplate>
<DockPanel x:Name="WarningGrid" VerticalAlignment="Top" Visibility="Collapsed">
<TextBlock Text="Warning" VerticalAlignment="Center"></TextBlock>
</DockPanel>
<DataTemplate.Triggers>
<Trigger Property="ContentControl.Content" Value="0">
<Setter TargetName="WarningGrid" Property="Visibility" Value="Visible" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</DockPanel>
I also tried it with SelectedIndex but also trigger is not working.
Thanks.
Change the Trigger to DataTrigger
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource AncestorType={x:Type ContentControl}}}" Value="0">
<Setter TargetName="WarningGrid" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>