How to change UI Button in WPF using MVVM - c#

With the Import button, I used :
<Button Command="{Binding ImportCommand}"
Content="Import"
Margin="5"
Width="100"></Button>
I disable Cap Nhat button if in Ma nhan su textbox and Ho Ten textbox was false. I used :
<Button Command="{Binding EditCommand}"
Content="Cập nhật"
Margin="5"
Width="100">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=Text1}"
Value="True">
<Setter Property="IsEnabled"
Value="False"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Everything worked OK!, but in UI Cap nhat button was changed, I want to change UI Cap nhat button like Import button.
Thank all for your help

Try to base the style on the style that is applied to the "Import" button:
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
Or set the IsHitTestVisible property instead of IsEnabled:
<DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=Text1}" Value="True">
<Setter Property="IsHitTestVisible" Value="False" />
</DataTrigger>

Related

How to use WPF Validation rules on a Listbox to enable a 'OK' button

I'm new with WPF and I have a problem. I want to enable a button only if en element of a Listbox is selected, otherwise it has to be disabled. I've tried with simple Validation Rule but it doesn't worked. Can anyone give me a hint? Ty
You don't use a ValidationRule to enable a Button but you could use a Button style with a trigger that binds to the SelectedItem property of the ListBox and sets the IsEnabled property of the Button to false if the SelectedItem property of the ListBox returns a null reference, e.g.:
<ListBox x:Name="lb">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
</ListBox>
<Button Content="Button">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=lb}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Ok, this works well ty. But I've to enable the button when 2 conditions are satisfied (a textbox not empty and an item of the listbox selected). How can i do this?
You could add another trigger:
<ListBox x:Name="lb">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
</ListBox>
<TextBox x:Name="txt" />
<Button Content="Button">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem, ElementName=lb}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=txt}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Change the visibility of a grid when a button has focus

I am working on a WPF application and I would like to change the visibility of a grid if an only if a button has focus. I have the following code to change the background of the button if it has focus. I know how to do this Programmatically, but I'd like to know how to get the same thing done in XAML.
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
You can name your Button and use a DataTrigger:
<Window
...
>
<Window.Resources>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<Button x:Name="butt">Hide</Button>
<Grid>
<Label Background="Yellow">Inside Grid</Label>
</Grid>
<Button>Steal focus</Button>
</StackPanel>
</Window>
EDIT
<Window
...
>
<Window.Resources>
<Style x:Key="CollapsedGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ToggleButton x:Name="butt">Hide</ToggleButton>
<Grid x:Name="GridA"
Style="{StaticResource CollapsedGridStyle}">
<Label Background="Yellow">Grid A</Label>
</Grid>
<Grid x:Name="GridB">
<Label Background="Green">Grid B</Label>
</Grid>
</StackPanel>
</Window>

WPF Edit Resource Dictionary dynamically passing parameters

I have a style defined in my resource dictionary so the style can be used in all over my application.
<Style x:Key="HyperlinkStyle" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource Color3}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource Color3Pressed}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource Color2NotEnabled}" />
</Trigger>
</Style.Triggers>
</Style>
I use the style in Datagrid like this :
<DataGridTemplateColumn Width="140*" CanUserReorder="False" CanUserResize="True" Header="">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate />
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource DatagridCellHyperlinkStyle}">
<Setter Property="IsEnabled" Value="{Binding Path=MyObject, Converter={StaticResource ConverterMyObject}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}" VerticalAlignment="Center">
<TextBlock Width="Auto" Height="Auto" TextTrimming="CharacterEllipsis">
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<InlineUIContainer TextDecorations="{Binding Path=TextDecorations, RelativeSource={RelativeSource AncestorType=TextBlock}}" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=TextBlock}}">
<ContentPresenter Width="Auto" Height="Auto" Content="{Binding DataContext.MyObject.Name, RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
</InlineUIContainer>
<Hyperlink.Style>
<Style TargetType="Hyperlink" BasedOn="{StaticResource HyperlinkStyle}">
<EventSetter Event="Hyperlink.Click" Handler="Clic" />
</Style>
</Hyperlink.Style>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
This works great but I would like to be able to have 2 colors in my style depending on a parameter.
For example, my datagrid has 1500 rows, I want to highlight 100 rows from the collection by changing their hyperlink color.
So I thought the best was to set the Tag property of the hyperlink to a custom value and use it in the style. Following this answer : https://social.msdn.microsoft.com/Forums/vstudio/en-US/d3424267-ed1f-4b30-90a1-5cca9843bd22/problem-making-a-trigger-on-the-tag-property?forum=wpf, I made the changes below :
xmlns:sys="clr-namespace:System;assembly=mscorlib"
First I've set the tag manually for each row to see if the style changes :
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
and added this trigger to my hyperlink's style:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte> <!-- My highlighted object -->
</Trigger.Value>
<Setter Property="Foreground" Value="{StaticResource Color1}" />
</Trigger>
But it doesn't work when I launch my application (I still have "Color3" whereas I want "Color1" when Tag is equals to 10.
I've checked the output there isn't any error.
I've tried to change "sys:Byte" by "sys:String" but the result was the same.
Do I need to change my approach for this problem ? I've read maybe we can't add trigger on Tag Property.
Thank you
I suggest if you set the tag like this
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
Then write the trigger in the same way:
<Trigger Property="Tag" Value="10">
...setter
</Trigger>
Or if in hyperlink you use Byte type as Tag:
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<Hyperlink.Tag>
<sys:Byte>10</sys:Byte>
</Hyperlink.Tag>
</Hyperlink>
Then same goes in the trigger:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte>
</Trigger.Value>
...setter
</Trigger>

WPF Styling Not Working as Expected

I have the following style applied to a Button (enabled by default):
<Style x:Key="DisableFoxProCancelButton"
TargetType="{x:Type Button}"
BasedOn="{StaticResource ButtonStyle}">
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=FoxProTableIsDirty}" Value="false">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
This works to disable the button when FoxProTableIsDirty is False.
I originally had this wired up as follows (disabled by default):
<Style x:Key="DisableFoxProCancelButton"
TargetType="{x:Type Button}"
BasedOn="{StaticResource ButtonStyle}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=FoxProTableIsDirty}" Value="true">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
But this second way did not work to disable the button when FoxProTableIsDirty is False.
The second style seemed to make more sense when I was writing the style as by default the button should be disabled until a change is made to the associated table and the changes need to be saved.
Can someone explain why the second one would not work as expected?
EDIT
Here is the code for the button using this style:
<Button Name="CancelFoxproChanges"
Content="Cancel"
Style="{StaticResource DisableFoxProCancelButton}"
DockPanel.Dock="Right"
HorizontalAlignment="Right">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction TargetObject="{Binding}"
MethodName="FoxProCancelButtonClicked" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
check if there is IsEnabled set in the Button element.
remove if it is set as triggers can not override local or inline values.
<Button Style="{StaticResource DisableFoxProCancelButton}" IsEnabled="False" />
in other way you can directly bind FoxProTableIsDirty to Button's IsEnabled, eg
<Button IsEnabled="{Binding FoxProTableIsDirty}" />
or via style setters
<Setter Property="IsEnabled" Value="{Binding FoxProTableIsDirty}" />
so as long as FoxProTableIsDirty is being resolved and notifying changes, this will enable/disable the button as desired

Change OnClick label color WPF

Im coming from a C# winforms background and I would normally do all this in code.
I have several Labels that I'm using as a menu.
When the mouse hovers over them the text changes color by:
<Page.Resources>
<SolidColorBrush x:Key="normalColor" Color="White" />
<SolidColorBrush x:Key="mouseOverColor" Color="Gold" />
<Style TargetType="Label" x:Key="menuItemStyle">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Foreground" Value="{StaticResource normalColor}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource mouseOverColor}"/>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Label x:Name="Label_Video1" Style="{StaticResource menuItemStyle}" Content="1.Video 1." FontSize="16" HorizontalAlignment="Left" Margin="25,74,0,0" VerticalAlignment="Top" MouseLeftButtonDown="Label_Video1_MouseLeftButtonDown" />
<Label x:Name="Label_Video2" Style="{StaticResource menuItemStyle}" Content="2. Video 2." FontSize="16" HorizontalAlignment="Left" Margin="25,105,0,0" VerticalAlignment="Top" MouseDown="Label_Video2_MouseDown"/>
When the user clicks a label I want it to stay a certin color (In this case Gold) and all the others to stay their normal colour. So if a label has been previously clicked and I click another label it will go from gold to white etc
When using WPF, you have to think slightly differently. We know that the Label control doesn't know when it has been clicked and it especially doesn't know when another Label element has been clicked... but some controls do. Thinking about it... a RadioButton has exactly this behaviour. Now this is where WPF really shines.
We can use RadioButtons and by providing them with a new ControlTemplate, we can make them look like plain text:
<Grid Background="Black">
<Grid.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<TextBlock Text="{TemplateBinding Content}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource AncestorType={
x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource
AncestorType={x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel Margin="5" Background="{x:Null}">
<RadioButton Content="1.Video 1." />
<RadioButton Content="2.Video 2." />
<RadioButton Content="3.Video 3." />
</StackPanel>
</Grid>
If you don't want the RadioButtons to be all together in a StackPanel, then you can use give them the same GroupName property value to ensure that they still operate as one group.

Categories

Resources