How to change the image source inside controltemplate? - c#

I have template in my MyResourceDictionary.xaml file like this
<ControlTemplate TargetType="{x:Type Button}" x:Key="ImageButtonTemplatepurpleSmall" >
<Grid>
<Image Source="images\button_purple_up_76.jpg" Name="image" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="image" Property="Source" Value="images\button_purple_hover_76.jpg" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="image" Property="Source" Value="images\button_purple_depressed_76.jpg" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Which is for applying image to button now
I just want to change this image source of this image inside grid like this
This is what i have tried
Image RecTangleObj = (Image)btnBack.Template.FindName("image", btnBack);
but some how it's always returns null value how can i change the image source of this one ?
updated
public override void OnApplyTemplate()
{
//base.OnApplyTemplate();
//Image RecTangleObj = (Image)btnBack.Template.FindName("image", btnBack);
//if (RecTangleObj != null)
//{
//}
}

OnApplyTemplate of window gets called when no child content is rendered on screen.
Place this code in Loaded event and it will work fine.

Related

C# WPF UI is not updated by datatrigger when I change a property in the listview item

I want to make a chess game in WPF, I decided to use listview to display my fields. I have a class named Field with properties. I have a list containing 64 fields and i changed to style of my listview in xaml so its look like a chess field. However, i have problem with the datatriggers. I need to change the picture (that will show the chess piece) when a property in that element in my list is changed.Nothing happens when the 'hasPiece' property is changed. I use INotifyPropertyChanged so i think i have no problem with the UI refresh, because i can update any displayed data in labels and testboxs. That is why i know i successfully changed the property when i selected 1 item, because i binded to a label. So when i select a field(an item) the 'hasPiece' property is updated to hidden, but the image still remains visible. I dont know much about datatriggers and I dont know what i did wrong.
<ListView Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Fields}" Width="410" SelectedItem="{Binding selectedField,Mode=TwoWay}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Height" Value="50"></Setter>
<Setter Property="Width" Value="50"></Setter>
<Setter Property="Margin" Value="0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Name="Border" BorderThickness="4,4,4,4" Background="{Binding Brush}" BorderBrush="{Binding Brush}">
<Grid Name="Grid" Background="{Binding Brush}">
<Image Name="PieceImage" Height="40" Width="40" Source="Images/something.jpg" >
</Image>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Grid" Property="Background" Value="{Binding MouseOverBrush}"/>
<Setter TargetName="Border" Property="BorderBrush" Value="{Binding MouseOverBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="Red"></Setter>
</Trigger>
<DataTrigger Binding="{Binding hasPiece}" Value="Hidden">
<Setter TargetName="PieceImage" Property="Visibility" Value="Hidden">
</Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
This is what i currently do when an item is selected:
private Field selected { get; set; }
public Field selectedField
{
get { return selected; }
set
{
selected = value;
// fieldId = selected.ID.ToString();
removeImage(selected.ID);
}
}
public void removeImage(int id)
{
foreach (Field item in Fields)
{
if (item.ID == id)
{
item.hasPiece = System.Windows.Visibility.Hidden;
fieldId = item.hasPiece.ToString();
}
}
}
I currently just want to test everything that needed, i know later i have to change things, but now i just want to know how i can change something in the style with datatriggers properly.
I solved the problem!
I implemented the INotifyPropertyChanged interface to my ViewModel, so the UI got updated when a variable which was created there is changed or when I added or removed items to my Observable collection which was also created there.
However if I want to edit my collection I have to implement this interface to my model.
My problem was not related to DataTrigger. My problem was the lack of INotifypropertyChanged in my model.

Mouse Hover trigger not working after changing background color programmatically

I have a project where I introduced a trigger for a button that changed the background color of the button when the mouse hovers it.
This is what it looks like:
<Window.Resources>
<Style x:Key="ButtonStyleDefault" TargetType="{x:Type Button}">
<Setter Property="Background" Value="White"/>
<Setter Property="Margin" Value="1.8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="FontWeight" Value="DemiBold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderThickness="1" BorderBrush="DarkGray">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
I have no issues with this and it works as expected.
These buttons are part of a numpad, so the same effect should happen when I press the number key on the keyboard.
This is the function that is reponsible for applying that effect on the button
private async void HandleButtonEffects(Button button)
{
if (button is null) {
return;
}
button.Background = new SolidColorBrush(Colors.LightGray);
await Task.Delay(80)
.ConfigureAwait(true);
button.Background = new SolidColorBrush(Colors.LightGray);
}
This also works fine. The problem is, the trigger stops working and hovering the button will have no effect.
My assumption is that the trigger is somehow a child of the Background property and, by overriding it, I am overriding the trigger as well.
I might be able to derive from button and create a public function that simulates the hovering and call that from the HandleButtoneEffect function? But I would like to avoid this as much as possible
How can I solve this?
button.Background = new SolidColorBrush(Colors.LightGray); - this line assigns local value to dependecy property. Local value has high precedence and trigger cannot override it.
You can call ClearValue to restore style effect:
private async void HandleButtonEffects(Button button)
{
if (button is null)
{
return;
}
button.Background = new SolidColorBrush(Colors.LightGray);
await Task.Delay(80).ConfigureAwait(true);
button.ClearValue(Button.BackgroundProperty);
}

Change an image on hover it with .bmp and .png image in WPF

I'm currently developing a C# WPF application and I want the image to change to another when I hover over it. Below is my code and work fine. I'm just curious that why if I put my image format as .png, the application will stop working although it had no error. How can I handle this problem in order to make the application work if I use .png image since I found that the image shown is quite pixelated when I used .bmp?
<Image x:Name="CloseBtn" Width="19" Height="19" Margin="457,5,11,343" MouseLeftButtonDown="CloseBtn_MouseLeftButtonDown">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="/Resources/closeIcon.bmp"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/Resources/closeIconHover.bmp"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>

WPF DataGridColumn style depending on tag

following the post in here, I've managed to create Tag property to the columns of my datagrid. Now, I would like to have different colors of columns depending on the value in tag. The goal is to have a table with days in columns, and today's current day would be highlighted (the date corresponding to column is stored in it's tag). Is it achievable? I found the solution based on coloring cells programmatically, but it doesn't suit my needs (multithreading issue - sometimes cell is painted before it stops to fill with data and then painting doesn't work).
Thanks in advance.
Edit:
Ok, I've followed the answer given by Nayeem Mansoori and came to this:
Style:
<Style x:Key="CellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="{TemplateBinding local:DataGridCellThemeProps.Brush}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#B2DCDCDC" />
<Setter Property="BorderBrush" Value="#B2DCDCDC" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Background" Value="#7FFFFFFF" />
<Setter Property="BorderBrush" Value="#7FFFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
DataGrid column:
<DataGridTextColumn local:DataGridCellThemeProps.Brush="Thistle"
Header="{x:Static props:Resources.Monday}"
Binding="{Binding Monday, Converter={StaticResource ZeroConverter}, Mode=TwoWay}"
CellStyle="{StaticResource CellStyle}" Width="75"/>
Class:
public static class DataGridCellThemeProps {
public static SolidColorBrush GetBrush(DependencyObject obj) {
return (SolidColorBrush)obj.GetValue(BrushProperty);
}
public static void SetBrush(DependencyObject obj, SolidColorBrush value) {
obj.SetValue(BrushProperty, value);
}
public static readonly DependencyProperty BrushProperty =
DependencyProperty.RegisterAttached(
"Brush",
typeof(SolidColorBrush),
typeof(DataGridCellThemeProps),
new FrameworkPropertyMetadata(Brushes.Black));
}
When I run my app, I get exception:
Exception: {"'Set property 'System.Windows.Setter.Value' threw an exception.' Line number '25' and line position '14'."}
Inner Exception: {"Expression type is not a valid Style value."}
I've double checked namespace of the class, it's correct. Any ideas?

"MouseOver" in Labels and Buttons in Xaml

I am very new to Xaml but I have been taking advantage of the WPF for a while. For that reason I have made the below method which I use to change the image of a label or button anytime I wanna implement a mouse over or mouse leave event.
public void SImpleImageHadler(dynamic thing, String Path) {
ImageBrush IB = new ImageBrush();
IB.ImageSource = new BitmapImage(new Uri("pack://application:,,,/" + Path, UriKind.Absolute));
thing.Background = IB;
}
I would like to know how I can do this purely using xaml so that I wouldn't have to make a lot of event handlers for each of my UI elements.
In the style triggers for your button you can put this type of code to change properties. To see a image specific example check out this question.
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
And from this answer is an image example:
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/MyProjectName;component/Images/MyImage.jpg" />
</Setter.Value>
</Setter>
</Trigger>
You should look into attached properties if you want to encapsulate such stuff for many different types of Buttons/Labels.
The final result should look like this:
<Button
ns2:MouseOverBackgroundChanger="YourURL"
/>
<Label
ns2:MouseOverBackgroundChanger="YourUrl2"
/>
This site has everything you need: http://msdn.microsoft.com/en-us/library/ms749011(v=vs.110).aspx (Attached Properties Overview)

Categories