WPF Visibility of a UI element based on combo selection - wpf

Trying to show a label only when a certain item in a combo is selected. Code should pretty much explain it.
<ComboBox Name="comboMyCombo">
<ComboBoxItem>Don't show the label</ComboBoxItem>
<ComboBoxItem>Show the label</ComboBoxItem>
</ComboBox>
<Label Visibility="Collapsed">This is my label
<Label.Style>
<Style>
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=comboMyCombo, Path=SelectedValue}" Value="Show the label">
<Setter Property="Label.Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

There are two issues here. First the default visibility should be specified in the style. But even with that it won't work because the binding on the trigger is comparing a SelectedValue, a ComboBoxItem object with a string object and that will never be equivalent. To keep the example simple, I've placed appropriate values in the ComboBoxItem's Tag properties. Although the actual implementation of the comparison will likely vary based on the specific needs of the app.
<ComboBox Name="comboMyCombo">
<ComboBoxItem Tag="Hide">Don't show the label</ComboBoxItem>
<ComboBoxItem Tag="Show">Show the label</ComboBoxItem>
</ComboBox>
<Label>This is my label
<Label.Style>
<Style>
<Setter Property="Label.Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=comboMyCombo, Path=SelectedItem.Tag}" Value="Show">
<Setter Property="Label.Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

A "cleaner" solution would be
<ComboBox>
<ComboBoxItem x:Name="iOne" Content="One"/>
<ComboBoxItem x:Name="iTwo" Content="Two"/>
<ComboBoxItem x:Name="iThree" Content="Three"/>
</ComboBox>
<Label Content="One is shown">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=iOne, Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

Related

Why is the DataTrigger to set the header of a DataGridColunm not working?

I am trying to set the header of the DataGrid columns according to a value of a property in my view model. I am using this code:
<DataGridTextColumn.Header>
<TextBlock>
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="My Default Header"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ucPrincipal, Path=DataContext.MyPrperty.ID}" Value="3" >
<Setter Property="Text" Value="Header 2"/>
</DataTrigger>
<DataTrigger Binding="{Binding DataContext.MyProperty.ID, RelativeSource={RelativeSource AncestorType={x:Type local:myUcViewType}}}" Value="4" >
<Setter Property="Text" Value="Header 3"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataGridTextColumn.Header>
But the header is always set to the default value. The values of ID are set to 3 and 4 correctly.
I am trying to use two different ways to get the value of the ID which is the source property that is used by the DataTrigger to set the header text.
Thanks.

Very weird logical error in WPF GridViewColumnHeader

I have custom treelistview and I put a checkbox in the first column of my treelistview. everything is ok but when I want to hide the checkbox column for other purpose (using variable SelectEnable) , it does not hide correctly(it hides but a blank area remains). This Problem happens when I load the data (I mean when treelistview is empty, the column is hidden).
here is some pieces of my xaml:
<Style x:Key="checkboxColumnStyle"
TargetType="GridViewColumnHeader">
<Setter Property="Width"
Value="0" />
<Setter Property="Visibility"
Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=SelectEnable}"
Value="False">
<Setter Property="Visibility"
Value="Hidden" />
<Setter Property="Width"
Value="0" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=SelectEnable}"
Value="True">
<Setter Property="Visibility"
Value="Visible" />
<Setter Property="Width"
Value="30" />
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="CellTemplate_checkBox">
<CheckBox IsChecked="{Binding IsSelected}"
VerticalAlignment="Center"
Style="{DynamicResource checkboxStyle}"
Tag="{Binding}"
Checked="CheckBox_Checked"
Unchecked="CheckBox_Checked" />
</DataTemplate>
<GridViewColumnCollection x:Key="gvcc">
<GridViewColumn CellTemplate="{StaticResource CellTemplate_checkBox}">
<GridViewColumnHeader Style="{DynamicResource checkboxColumnStyle}"
MaxWidth="0">
<CheckBox x:Name="chechBoxAll"
Style="{DynamicResource checkboxStyle}"
Checked="chechBoxAll_Checked"
Unchecked="chechBoxAll_Checked" />
</GridViewColumnHeader>
</GridViewColumn>
<!--Other Columns -->
</GridViewColumnCollection>
How can i fix this?
You probably want Visibility.Collapsed instead of Visibility.Hidden.
Hidden means the element is there but cannot be seen (similar to Opacity of 0), whereas Collapsed causes the layout arrangement to happen as though the element does not exist (no width and no height).

Can't bind to property of one control in a DataTrigger to other control in different grids

I have two controls in this example but in the real application i have many more whick depending of the value of the property Content of a Label in Grid one (for example), some other Labels, TextBoxes, TextBlocks and Buttons will be Visible or Collapsed in Grid two (for example).
But to simplify my problem i will have a simplified example...
<Grid Name="gridOne">
<Label Content="{Binding Collection.Name}" Name="lblCaption"/>
</Grid>
<Grid Name="gridTwo">
<Label Content="My Label" Visibility="Collapsed">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblCaption, Path=Content}" Value="Employers">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<TextBox Text="{Binding EmployerName}" Visibility="Collapsed">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblCaption, Path=Content}" Value="Employers">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
I know that this won't work too if i set the property Visibility as Collapsed for default in control but i have many collections and i don't think that having one DataTrigger for each Collection is good way to achieve it. Anyway one problem comes when binding controls in different grids and other in handling the property Visibility in a good way.
Thanks in advance!
Local value takes precedence over style triggers. Move the visibility intialization inside the style as:
<Label Content="My Label">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lblCaption, Path=Content}" Value="Employers">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

wpf: override label content when currently bound item is null

I want to set a Label (or TextBox) default string as long as the binding value is null. This works fine for any other property than Content, for example:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label}">
<Label.ContentStringFormat>Details for pump curve: {0}</Label.ContentStringFormat>
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/}" Value="{x:Null}">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
The above will change the background of the label to red as long as there is no CurrentItem in the pumpCurvesViewSource, but what I really want to do is change the background trigger to this:
<Setter Property="Content" Value="No pump curve selected"></Setter>
But this does not work (I'm guessing it is because the Content is already bound and my setting would override the binding).
Does anyone know how to accomplish this?
have you tried TargetNullValue?
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label, TargetNullValue='No pump curve selected'}">
If found a way of accomplishing the same thing, but with a bit more code than I liked:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/Label}">
<Label.ContentStringFormat>Details for pump curve: {0}</Label.ContentStringFormat>
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/, Mode=OneWay, Converter={StaticResource isNullConverter}}" Value="True">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label Content="No pump curve selected">
<Label.Style>
<Style TargetType="Label" BasedOn="{StaticResource header}">
<Style.Triggers>
<DataTrigger Binding="{Binding Source={StaticResource pumpCurvesViewSource}, Path=/, Mode=OneWay, Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
the shortest answer would be:
<Label Content="{Binding Source={StaticResource pumpCurvesViewSource, FallbackValue=Your Default String}, Path=/Label}">

WPF Listbox - Empty List Display Message

Can anyone suggest the best way to display a Textblock (with a text such as "List Empty") so that it's visibility is bound to the Items.Count.
I have tried the following code and can't get it to work, so think that I must be doing it wrong.
<ListBox x:Name="lstItems"
ItemsSource="{Binding ListItems}">
</ListBox>
<TextBlock Margin="4" FontStyle="Italic" FontSize="12" Text="List is empty" Visibility="Collapsed">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lstItems, Path=Items.Count}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
The problem in your code is that setting the value of Visibility in the text block itself has higher priority than setting it in the style. So, even when the trigger occurs, the setting inside the trigger has no effect. Change the XAML to:
<TextBlock Margin="4" FontStyle="Italic" FontSize="12" Text="List is empty" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lstItems, Path=Items.Count}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Where the setting of Visibility is all in the style and it works (at least in my demo project).

Resources