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
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.
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);
}
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>
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?
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)