I'm trying to collapse a CheckBox
through Visibility
if the selected item of a ComboBox
is null
or empty. The source is a list of objects having two string properties: Code
and Name
.
I'm using a trigger binded to the ComboBox
text.
<ComboBox x:Name="VideoSub" SelectedItem="{Binding SubSelection, Mode=TwoWay}"
ItemsSource="{Binding Path=SubsSource}"
IsEnabled="{Binding HasItems, RelativeSource={RelativeSource Self}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<CheckBox Width="80" IsEnabled="{Binding ElementName=VideoSub, Path=IsEnabled}"
HorizontalAlignment="Right" Margin="0,10,0,0">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=VideoSub, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
CodePudding user response:
It is more directly to use event SelectionChanged
to control whether components are displayed.
I wrote some demo code, hope it helps:
MainWindow.xaml
<Window x:Class="TestWpfApp.MainWindow"
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"
mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
<StackPanel>
<ComboBox Name="MyComboBox" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem Content="Code"></ComboBoxItem>
<ComboBoxItem Content="Name"></ComboBoxItem>
</ComboBox>
<CheckBox Name="MyCheckBox" Visibility="Collapsed" />
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace TestWpfApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.MyComboBox.SelectedItem == null)
{
this.MyCheckBox.Visibility = Visibility.Collapsed;
}
else
{
this.MyCheckBox.Visibility = Visibility.Visible;
}
}
}
}
Furthermore, sometimes it's easier to use procedure (such as functions/methods) than definition (such as triggers etc) in programming :)
CodePudding user response:
If you are using a DataTemplate
, you should not trigger on elements inside it, but its data. If you want to hide the CheckBox
when the SelectedItem
is null
, use the x:Null
markup extension for comparison.
<DataTrigger Binding="{Binding SelectedItem, ElementName=VideoSub}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
As you bind Name
to the TextBlock
, you can add a DataTrigger
to your style, that compares it to the static empty string. There is no need to reference the TextBlock
itself.
<DataTrigger Binding="{Binding SelectedItem.Name, ElementName=VideoSub}" Value="{x:Static system:String.Empty}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
Note that you have to add an XML namespace for the String
type.
- .NET Core:
xmlns:system="clr-namespace:System;assembly=System.Runtime"
- .NET Framework:
xmlns:system="clr-namespace:System;assembly=mscorlib"
Here the complete style that checks for null
and emptyness.
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=VideoSub}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem.(local:PersonModel.Name), ElementName=VideoSub}" Value="{x:Static system:String.Empty}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
By the way, you probably do not need a DataTemplate
at all, if you just want to display a property as text in the ComboBox
. Set the DisplayMemberPath
instead.
<ComboBox x:Name="VideoSub" SelectedItem="{Binding SubSelection, Mode=TwoWay}"
ItemsSource="{Binding Path=SubsSource}"
IsEnabled="{Binding HasItems, RelativeSource={RelativeSource Self}}"
DisplayMemberPath="Name"/>
CodePudding user response:
Just bind to SelectedItem
:
<CheckBox Width="80" IsEnabled="{Binding ElementName=VideoSub, Path=IsEnabled}"
HorizontalAlignment="Right" Margin="0,10,0,0">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=VideoSub}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
An object itself "having two string properties: Code and Name" cannot be "empty".
There either is an item selected or there isn't.