Textblock collapsed using space - c#

I have a C# WPF project. I am using an ObservableCollection<T> in my viewmodel class.
I have a ListView in xaml file. There is TextBlock inside the ListView binding to the ObservableCollection<T>.
I want to collapse them by DataTrigger. The result is that those TextBlock is collapsed but still using space. I would like to ask how to fix it?
Here is the ListView I am using:
<ListView Grid.Row="1" ItemsSource="{Binding ServiceObjects}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ServiceName}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsCollapsed}" Value="true">
<Setter Property="Foreground" Value="#FFBF00" />
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Try this:
<Style TargetType="ListBoxItem" x:Key="LstBoxItemStyle">
<Setter Property="MinHeight"
Value="0" />
<Setter Property="IsEnabled"
Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsCollapsed}" Value="True">
<Setter Property="IsEnabled"
Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
and
<ListView Grid.Row="1"
ItemsSource="{Binding ServiceObjects}"
ItemContainerStyle="{StaticResource LstBoxItemStyle}">
Or use filters https://learn.microsoft.com/pl-pl/dotnet/desktop/wpf/data/how-to-filter-data-in-a-view?view=netframeworkdesktop-4.8

Related

XAML DataTrigger Not Firing?

I have a property in my ModularClientModule class called ExistsOnDisk. When that property is set to false, I want to disable the CheckBox. For some reason, this does not seem to work despite me putting it last in the Triggers XAML block, which means it should be the last thing to fire. I.e, nothing should be interfering. I know my code-behind should be correct because as you will see below, I have another control which receives the update and fires fine.
This one here responds to the ExistsOnDisk property change without issue, and strikesthrough the text:
GridViewColumn x:Name="FileNameHeader" Header="File Name">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:ModularClientModuleUI}">
<TextBlock Text="{Binding Filename}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="False">
<Setter Property="TextDecorations" Value="Strikethrough"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
This one here does not, and the checkbox remains enabled:
<GridViewColumn x:Name="StatusHeader" Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:ModularClientModuleUI}">
<StackPanel>
<CheckBox x:Name="ClientModuleStatusCheckBox" Margin="5, 0" Click="ClientModuleStatusCheckBox_Click" IsEnabled ="{Binding Client.Online}">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource MahApps.Styles.CheckBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadState}" Value="Loaded">
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Unloaded">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Loading">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
What could be going on here?
Set the default value of the IsEnabled using a Setter and remove IsEnabled ="{Binding Client.Online}" from the <CheckBox> element:
<CheckBox x:Name="ClientModuleStatusCheckBox" Margin="5, 0" Click="ClientModuleStatusCheckBox_Click">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource MahApps.Styles.CheckBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding LoadState}" Value="Loaded">
<Setter Property="IsChecked" Value="True" />
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Unloaded">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding LoadState}" Value="Loading">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ExistsOnDisk}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
Also note that you shouldn't use more than one trigger on the same bool property.

ContentStringFormat never changes by Setter Property in DataTrigger

In my user control I want to have label displaying Text from resource depending on viewmodel property Location value and with different format.
I implemented it by defining DataTrigger for each Location value
<Style x:Key="LocationValueHelper" TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding Location}" Value="HomeViewModel">
<Setter Property="Content" Value="" />
<Setter Property="ContentStringFormat" Value="{}{0}???"/>
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="FirstViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}+++"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=First}" />
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="SecondViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}---"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Second}" />
</DataTrigger>
<DataTrigger Binding="{Binding Location}" Value="ThirdViewModel">
<Setter Property="ContentStringFormat" Value="{}{0}***"/>
<Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Third}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Label Foreground="White" HorizontalAlignment="Center" FontSize="40" Style="{StaticResource LocationValueHelper}" />
The problem is that format never changes from the first one (???) - HomeViewModel selected first - although text changing works.
I have
Home???
First???
Second???
Third???
instead of
Home???
First+++
Second---
Third***
There are a lot of discussions, using Labels and ContentStringFormat does not work like expected or desired:
WPF StringFormat on Label Content
StringFormat VS ContentStringFormat
...
The reason seems to be the template based implementation under the hood, since the content also could contain other data than strings. To solve your problem, my proposal is to use a TextBlock, which works quite smooth like this:
<StackPanel>
<CheckBox IsChecked="{Binding MyFlag}"/>
<TextBlock HorizontalAlignment="Center" FontSize="40">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding MyFlag}" Value="False">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}+++'}" />
</DataTrigger>
<DataTrigger Binding="{Binding MyFlag}" Value="True">
<Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}???'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>

How to bind to a SelectedValue data context property in WPF?

I have a listbox that display some model items.
I would like to hide some control below the listbox based on the boolean value of the model item associated with the selected listbox item.
I tried the following but it did not work:
1) set the ListBox SelectedValuePath="MyModelBooleanProperty"
2) add a data trigger to the control that I want to hide as follows
<DataTrigger Binding="{Binding ElementName=FolderList, Path=SelectedValue}" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FolderList, Path=SelectedValue}" Value="True">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
I used this and it worked. Also make sure you don't explicitly set Visibility of TextBlock that overrides whatever the Style does.
<ListBox
x:Name="FolderList"
ItemsSource="{Binding Source={StaticResource ViewModel}, Path=List}"
SelectedValuePath="SomeBooleanProperty">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SomeStringProperty}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=FolderList, Path=SelectedValue}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=FolderList, Path=SelectedValue}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
My Text Block
</TextBlock>

How to set TabIndex in Hyperlink?

I am new to WPF, I dont know how to do this.
I tried following code -
<TextBlock Grid.Column="3" Grid.Row="3" Visibility="{Binding Path=CanCreate, Converter={StaticResource BoolVisibilityConverter}}">
<Hyperlink KeyboardNavigation.TabIndex="2" Command="{Binding Path=CreateCommand}">Create
<Hyperlink.Style>
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CanCreate, Converter={StaticResource BoolVisibilityConverter}}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</Hyperlink.Style>
</Hyperlink>
</TextBlock>
Visibility depends on CanCreate Dependency property. Here IsTabStop is not enabling. Can anyone suggest the solution. Thanks in advance.
Requirement
I want to set TabIndex to hyperlink when it is visible.
You don't need a converter in the DataTrigger change your Hyperlink.Style to:
<Hyperlink.Style>
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CanCreate}" Value="True">
<Setter Property="KeyboardNavigation.IsTabStop" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</Hyperlink.Style>
EDIT: You may also want to remove focus when your TextBlock and Hyperlink is invisible, you can do it by adding another DataTrigger:
<Hyperlink.Style>
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CanCreate}" Value="True">
<Setter Property="KeyboardNavigation.IsTabStop" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=CanCreate}" Value="False">
<Setter Property="Focusable" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Hyperlink.Style>

Calling a Image style

Is there any way to create a call'able image style? I have multiple buttons on a user control that have the same button and button image style. I can set the button style so that it can be called from the style (dynamic resource) of the button.
Here is an example of my code and the image style code:
<Grid.Resources>
<Style TargetType="Button"
x:Key="ButtonEditSaveStyle">
<Setter Property="IsEnabled"
Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding CanEdit}"
Value="True">
<Setter Property="IsEnabled"
Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button Width="32"
Height="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Name="gdEmployeeInfo_btnUpdateRecord"
Click="gdEmployeeInfo_btnUpdateRecord_Click"
Style="{DynamicResource ResourceKey=ButtonEditSaveStyle}"/>
I want to set my code up so that I can have the call above an have an additional call or a combined call to set the image style as well. I know I can have the image style in the button (as shown in this next code), but I want to have one place to update multiple buttons using the same style setup. Image style code:
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source"
Value="edit_32.png" />
<Setter Property="Stretch"
Value="Uniform" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditing}"
Value="True">
<Setter Property="Source"
Value="save_smallest.png" />
<Setter Property="Stretch"
Value="Uniform" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Figured out the answer to my question. This set of code allows me to use dual style setting while creating only one call for the button's style:
<!--SaveEditImageSwitch-->
<Image x:Key="SaveEditImage" x:Shared="False">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source"
Value="edit_32.png" />
<Setter Property="Stretch"
Value="Uniform" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditing}"
Value="True">
<Setter Property="Source"
Value="save_smallest.png" />
<Setter Property="Stretch"
Value="Uniform" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<!--ButtonEditSaveStyle-->
<Style TargetType="Button"
x:Key="ButtonEditSaveStyle">
<Setter Property="IsEnabled"
Value="False" />
<Setter Property="Content"
Value="{DynamicResource ResourceKey=SaveEditImage}" />
<Style.Triggers>
<DataTrigger Binding="{Binding CanEdit}"
Value="True">
<Setter Property="IsEnabled"
Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
<Button Width="32"
Height="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Name="gdEmployeeInfo_btnUpdateRecord"
Click="gdEmployeeInfo_btnUpdateRecord_Click"
Style="{DynamicResource ResourceKey=ButtonEditSaveStyle}">

Categories