Change Image Source when the Parent Button change its enabled state - c#

I have this XAML code:
<Button x:Name="ButtonUpdate" IsEnabled="False">
<Image Source="Images/update gray.png" Name="ImgUpdate" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Source" Value="Images/update.png" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
I want that when ButtonUpdate is enabled:
ButtonUpdate.IsEnabled = true;
the ImgUpdate.Source become "Images/update.png", and when ButtonUpdate is not enabled:
ButtonUpdate.IsEnabled = false;
the ImgUpdate.Source become "Images/update gray.png" using data binding.
My XAML code doesn't work. Where is the error? How can I fix it?

Your Trigger applies to the Image, not the button, so the IsEnabled property that is monitored in this case is the Image.IsEnabled property, which is not what you want.
You can either create a Style for the Button and use a Trigger in that Style to change the Content of the button based on the IsEnabled state, or you could create a ControlTemplate with the Image as the content of the Button and change the Source of the Image based on the enabled state of the button.
This Answer seems to provide the specifics for what you're asking.

The image source property should be in this format:
"/«YourAssemblyName»;component/«YourPath»/«YourImage.png»"
Example
<Image Source="/WPFApplication;component/Images/Start.png" />
See this post for more info:
WPF image resources

Related

Bind a custom property to a template in WPF

I want to create a template for a button, that will show an image (icon) instead of text.
I want to be able to assign different images to different instances of that button, for example:
<Button Style="{StaticResource iconButton}" ImageSource="Sources/icon.png">
or alternatively:
<Button Style="{StaticResource iconButton}">
<Image Source="...">
</Button>
(but I still want to be able to style the image in the template, so I wouldn't need to worry about color and size when I use it - so simply rendering the image as content won't do).
Example code:
Here I am using the image as a mask to render it in whatever color I want:
<Style TargetType="Button" x:Key="iconButton">
<Style.Resources>
<!-- add the "content to image source" converter-->
<converters:ContentToImageSourceConverter x:Key="ContentToImageSourceConverter"/>
</Style.Resources>
<Setter Property="Foreground" Value="{DynamicResource foreground_color}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Margin="5">
<Ellipse x:Name="circle" Width="45" Height="45" Fill="{DynamicResource foreground_color}" Opacity="0"/>
<Ellipse Width="45" Height="45" Fill="{DynamicResource foreground_color}">
<Ellipse.OpacityMask>
<!--How to accomplish this?-->
<ImageBrush ImageSource="{TemplateBinding Property=Content "/>
</Ellipse.OpacityMask>
</Ellipse>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="circle" Property="Opacity" Value="0.15"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="circle" Property="Opacity" Value="0.3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Have a look at the line where it says "how to accomplish this". I am using an image as a source but I want the image to be defined whenever you use the button, for example:
<Button Style="{StaticResource iconButton}" DockPanel.Dock="Right">
<Image Source="/Sources/settings_icon.png"/>
</Button>
I do not want to simply render the image as a content of the button because I'm using it as a mask for something else, thus I can change the foreground color and have the icons render in a different color.
I would do a custom control, with one dependency property of the image source. Have you tried this?
And then you will use it like this
<MyCustomButton DockPanel.Dock="Right" ImageSource = Sources/settings_icon.png">
</MyCustomButton>
The simplest way to do it:
Add UserControl to your project
In xaml just add one button
Add style to this control and set it to the button
Add dependency property, and link it to the image source (in style) by binding. Here you need also to have specified a source of binding.
{Binding RelativeSource={RelativeSource Self}}
Second way:
Make an class which is deriving form the Button class.
Add one dependency property, with the image source object.
In Style Specify a binding for the source property of the image control, it has to have the same name as he dependency property. I think that you will also need to specify the source of the binding as a Ancestor, because it could not be able to find the binding source.
Check here to see the syntax.
Binding to an ancestor in WPF
In both ways the usage will look same.

Changing Button style's alternative like Bold button in Microsoft word in wpf

my question is that
is there any way for implementation a button like bold Button in word when click its background will be change , ""with out get boolean var"" ,
that means I want to know is there ant event or trigger or visualstate in xaml order to implement a button style when click its style will be change(during Working like word) and its style will come back to Normal style when click again ?
image Bold Btn
The way to do this is with style triggers. Like so...
<ToggleButton Content="B" FontSize="20" Height="40" Width="40">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="FontWeight" Value="ExtraBold"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>

Set commands for a control in WPF

I am using DevExpress for a WPF application, I want to hit a toggle button and make the contents in a richTextBox bold, the manual which is provided here suggests to use ToggleFontBoldCommand as the command. In my WPF application in the xaml file I have added the following code:
<telerik:RadToggleButton CommandTarget="{Binding ElementName=doc}" Command="com:ToggleFontBoldCommand" Content="B"/>
doc is a richTextBox. com is the namespace of DevExpress commands' namespaces (xmlns:com="clr-namespace:DevExpress.XtraRichEdit.Commands; assembly=DevExpress.RichEdit.v16.1.Core"). The point is that Visual Studio can not find the command. I believe that I am wrong with the CommandTarget but I do not know what is wrong.
I'm just using the standard WPF ToggleButton and TextBox in this answer, but I believe the solution should also work with your telerik and DevExpress controls.
If all you want is to make the text in the RichTextBox bold when the RadToggleButton has been clicked you should be able to side step the whole command thing and use something similar to the following:
<ToggleButton x:Name="BoldToggle" />
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=BoldToggle}" Value="true">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
The style on the TextBox changes the FontWeight property from "Normal" to "Bold" when the ToggleButton's IsChecked property is "true".
Does this get you what you need?

Set textbox text to current time on button click

I have a UserControl that I'm writing that will have a TextBox and Button. When the user clicks the button, I'd like the current date/time to be placed into the TextBox. The code below has two issues:
For some reason the binding is throwing an exception "Two-way binding requires Path or XPath".
If I just set the value to something like "Test", then it works but only while the button itself is pressed, once I lift the mouse button the text goes away.
In essence, I'd like the value to be set at mouse click not during. I'd like to keep this pure xaml if possible, but I understand if it needs to be in the code-behind. Any help would be appreciated!
<Button x:Name="ClockGo">
<Image Source="/Best.Controls;component/Resources/clock_go.png" />
</Button>
<TextBox HorizontalAlignment="Stretch">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ClockGo, Path=IsPressed}" Value="True">
<Setter Property="Text" Value="{Binding Source={x:Static sys:DateTime.Today}, StringFormat='{}{0:MM/dd/yyyy}'}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
You should be able to get rid of "Two-way binding requires Path or XPath" exception by setting the binding mode to OneWay. Textbox has a two way binding by default and I believe the exception is due to the value conversion.
<Setter Property="Text" Value="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='{}{0:MM/dd/yyyy hh:mm:ss}', Mode=OneWay}" />
On your second point where the value only shown when the button is pressed and goes away after button click is released, this is the expected behaviour. The Trigger Setter only apply when the binding condition is true, it will be revert to default value when the condition no longer true.
Please refer to MSDN site on the remark section which spells out above behaviour: http://msdn.microsoft.com/en-us/library/system.windows.trigger.aspx
Unless you have a very strong reason to stick with XAML based solution, code behind seems to be the better option here instead of tweaking with triggers.

WPF Datatrigger on button based on datagrid

Currently, I have the following datatrigger:
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ScheduleDataGrid, Path=HasItems}"
Value="false">
<Setter Property="Button.IsEnabled" Value="false"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
and I have two buttons that adds/deletes a row in a datagrid
<Button Name="BtnAddPoint" Content="Add" Width="70" Margin="10 0 10 0" Click="BtnAddSchedule_Click"></Button>
<Button Name="BtnDeletePoint" Content="Delete" Width="70" Click="BtnDeleteSchedule_Click"></Button>
I have two questions.
Currently, the above trigger disables both of the button when I only want it to disable the delete button. Setting the targetname of the setter to the delete button doesn't work. Can I make the trigger target a particular button?
Also, I'd like the delete button to be only enabled when a grid item is selected rather than checking for the item count. Is this possible?
You should use Style with key if you want to assign it to appropriate button:
<Style x:Key="DeleteButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Button.IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ScheduleDataGrid, Path=SelectedItem}" Value="{x:Null}">
<Setter Property="Button.IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
In BtnDeletePoint button you should add style:
<Button Name="BtnAddPoint" Content="Add" Width="70" Margin="10 0 10 0" Click="BtnAddSchedule_Click"></Button>
<Button Name="BtnDeletePoint" Content="Delete" Width="70" Click="BtnDeleteSchedule_Click" Style="{StaticResource DeleteButtonStyle}"></Button>
Instead of checking HasItems and writing another trigger to check if grid has selected item, you can write trigger and check if SelectedItem is null. SelectedItem property gives you information if grid has items and if user selected one of them.
If both Buttons share the same Style and therefore have the same Trigger, then they are both going to be disabled under the same circumstances (in this case, when the DataGrid has 0 items).
In order to disable the Delete Button under different circumstances you will need to create a separate Style with a different Trigger and apply that style to BtnDeletePoint. Since I don't see you setting the Style in the declaration of the buttons, I would guess the trigger belongs to an Implicit Style for Button, so you'll need to assign an x:Key to the new style so that you can assign it to your delete button:
<Style x:Key="DeleteButtonStyle" TargetType="Button">
<!-- Setters -->
<!-- Triggers -->
</Style>
<Button Name="BtnDeletePoint" Style="{DynamicResource DeleteButtonStyle}" Content="Delete" Width="70" Click="BtnDeleteSchedule_Click"/>
As for the trigger to enable the delete button when only a single item is selected, if you don't want to use the Count of the SelectedItems property on the DataGrid, then you would need to use a Converter to determine the selection state of the grid - there are no other DependencyProperties on the DataGrid that I'm aware of that will provide you that information.
Also, I'm not sure of the context without more of the code, but don't believe you want a DataTrigger in this case - you should be fine with a standard Trigger.

Categories