WPF: Change Progress-Bar color with IMultiValueConverter - wpf

Ok so i have this properties in my View Model:
public double Progress
{
get { return _progress; }
set
{
_progress= value;
OnPropertyChanged();
}
}
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged();
}
}
And as you can see this implement INotifyPropertyChanged.
This is my Progress-Bar:
<ProgressBar Name="progressBarColumn"
Minimum="0"
Maximum="100"
Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}"
Width="{Binding Path=Width, ElementName=ProgressCell}"
Style="{StaticResource CustomProgressBar2}"/>
And my Style:
<Style x:Key="CustomProgressBar2" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar" >
<Grid x:Name="Root">
<Border Name="PART_Track"
CornerRadius="0"
Background="Blue"
BorderBrush="Blue"
BorderThickness="1"/>
<Border Name="PART_Indicator"
CornerRadius="0"
Background="Gray"
BorderBrush="Gray"
BorderThickness="1"
HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So this works fine, my Progress-Bar color is Blue and fill with Gray color.
Now i want to add two more things and dont know when:
1. When my Progress-Bar reach the Value of 100 i want it Background become Green.
When my Property called IsChecked is False i want that my Background become Red.
So until here i have this IMultiValueConverter:
public class ProgressToPropgressBarBackgroundConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// Do my stuff
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The problem is that i dont know where to add my converter and how.
EDIT:
<Style x:Key="CustomProgressBar2" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar" >
<Grid x:Name="Root">
<Border Name="PART_Track"
CornerRadius="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Background}"
BorderThickness="1"/>
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{TemplateBinding Foreground}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="1"
HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}">
<Setter Property="Foreground" Value="DarkCyan"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked}" Value="true">
<Setter Property="Background" Value="{DynamicResource ProgressBackgroundColor}" />
<Setter Property="Foreground" Value="{DynamicResource ProgressBarFillColor}" />
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked}" Value="false">
<Setter Property="Background" Value="#55B3B3B6" />
</DataTrigger>
</Style.Triggers>
</Style>

You logic is simple enough you can avoid a converter and simply use triggers in your style:
<Style.Triggers>
<DataTrigger Binding=“{Binding Progress}” Value=“100”>
<Setter Property=“Background” Value=“Green” />
</DataTrigger>
<DataTrigger Binding=“{Binding IsChecked}” Value=“True”>
<Setter Property=“Background” Value=“Red” />
</DataTrigger>
</Style.Triggers>
Then you need to update your control template to properly respect the control’s Background property. You can use TemplateBinding for this:
<Border Name="PART_Track"
CornerRadius="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Background}"
BorderThickness="1"/>
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{TemplateBinding Foreground}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="1"
HorizontalAlignment="Left" />
And if you want the same Blue and Gray default colors, add them to the style:
<Setter Property=“Background” Value=“Blue”/>
<Setter Property=“Foreground” Value=“Gray”/>

Related

WPF: Update foreground with value from dependancy property in ControlTriggers

I have the following style for a CustomControl in WPF:
<Style TargetType="{x:Type local:BooleanIndicator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BooleanIndicator}">
<Border Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<StackPanel Orientation="Horizontal"
Margin="3">
<Label Name="symbol"
FontFamily="Segoe MDL2 Assets"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
Content="{TemplateBinding Symbol}"/>
<ContentPresenter Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsActive"
Value="True">
<Setter Property="Foreground"
Value="{Binding ActiveForeground, RelativeSource={RelativeSource TemplatedParent}}" />
</Trigger>
<Trigger Property="IsActive"
Value="False">
<Setter Property="Foreground"
Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With a dependency property "ActiveForeground":
public Brush ActiveForeground
{
get { return (Brush)GetValue(ActiveForegroundProperty); }
set { SetValue(ActiveForegroundProperty, value); }
}
public static readonly DependencyProperty ActiveForegroundProperty =
DependencyProperty.Register("ActiveForeground",
typeof(Brush),
typeof(BooleanIndicator),
new UIPropertyMetadata(Brushes.DarkGreen));
However it does not work - the Foreground colour is not updated. If I change the colour in the trigger directly, e.g. <Setter Property="Foreground" Value="DarkGreen" /> it works... What is going on?
You must set the TargetName of a Setter in a ControlTemplate:
<Setter Property="Foreground" TargetName="symbol" Value="{Binding ActiveForeground, RelativeSource={RelativeSource TemplatedParent}}" />
If you want to set the Foreground property of the control itself, you should use a Style trigger:
<Style TargetType="{x:Type local:BooleanIndicator}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BooleanIndicator}">
<Border Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<StackPanel Orientation="Horizontal"
Margin="3">
<Label Name="symbol"
FontFamily="Segoe MDL2 Assets"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
Content="{TemplateBinding Symbol}"/>
<ContentPresenter Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray" />
<Style.Triggers>
<Trigger Property="IsActive" Value="True">
<Setter Property="Foreground"
Value="{Binding ActiveForeground, RelativeSource={RelativeSource Self}}" />
</Trigger>
</Style.Triggers>
</Style>

XAML Listbox Styled as radio button group with Title

I have this style:
<Style x:Key="RadioButtonList" TargetType="{x:Type ListBox}">
<!-- ControlTemplate taken from MSDN http://msdn.microsoft.com/en-us/library/ms754242.aspx -->
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="80"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
Name="Border"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2">
<ScrollViewer
Margin="0"
Focusable="false">
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="Transparent" />
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="theBorder" Background="Transparent">
<RadioButton Focusable="False"
IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
Used as this :
<ListBox
Grid.Column="2"
Style="{StaticResource RadioButtonList}"
ItemsSource="{Binding ModosConsultaSaldos}"
DisplayMemberPath="Description"
SelectedItem="{Binding ModoConsultaSaldos,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
Shows something like this:
But now I want to add a Title using the same Style,
Is this posible? How ?
This could be done in a number of ways. The easiest is simply to stick a label in front of the ListBox in the XAML whenever you use it. But if you want to enforce a consistent style, you'll want something better than that.
We could add properties to ListBox by writing a subclass of ListBox that adds a Header property (I'm going to call it Header instead of Title because that's what a built-in WPF control would call it).
But a slightly more flexible option is to write the Header property as an attached property. We'll also throw in a HeaderTemplate attached property as well, so you can style the header content appropriately. This is common WPF practice in controls that have headers, such as MenuItem or GroupBox. Those WPF controls have HeaderTemplateSelector and HeaderStringFormat properties as well; I'll leave those as an exercise for the student.
First, the attached properties: This is all boilerplate except for the names and types.
public static class ListBoxEx
{
public static Object GetHeader(ListBox obj)
{
return (Object)obj.GetValue(HeaderProperty);
}
public static void SetHeader(ListBox obj, Object value)
{
obj.SetValue(HeaderProperty, value);
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.RegisterAttached("Header", typeof(Object), typeof(ListBoxEx),
new FrameworkPropertyMetadata(null) { AffectsMeasure = true, AffectsParentMeasure = true });
public static Object GetHeaderTemplate(ListBox obj)
{
return (Object)obj.GetValue(HeaderTemplateProperty);
}
public static void SetHeaderTemplate(ListBox obj, Object value)
{
obj.SetValue(HeaderTemplateProperty, value);
}
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.RegisterAttached("HeaderTemplate", typeof(Object), typeof(ListBoxEx),
new FrameworkPropertyMetadata(null) { AffectsMeasure = true, AffectsParentMeasure = true });
}
Now we'll add these to the Template:
...
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
Name="Border"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl
Content="{TemplateBinding local:ListBoxEx.Header}"
ContentTemplate="{TemplateBinding local:ListBoxEx.HeaderTemplate}"
/>
<ScrollViewer
Margin="0"
Focusable="false"
Grid.Row="1"
>
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Grid>
</Border>
And we'll give your Style another setter, to create a default header template that does the underlining you had in your screenshot:
<Setter Property="local:ListBoxEx.HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Label
Content="{Binding}"
BorderBrush="Black"
BorderThickness="0,0,0,1"
HorizontalAlignment="Left"
/>
</DataTemplate>
</Setter.Value>
</Setter>
And we use it like this:
<ListBox
Style="{StaticResource RadioButtonList}"
ItemsSource="{Binding ModosConsultaSaldos}"
local:ListBoxEx.Header="Saldos"
...
/>

WPF: Change Progress-Bar color according its value and View Model property

Ok so i have this property in my View Model:
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged(); // I also try OnPropertyChanged("IsChecked");
}
}
And as you can see this implement INotifyPropertyChanged.
When this property is changing i can see the it notify and get the correct value.
This is my Progress-Bar:
<ProgressBar Name="progressBarColumn"
Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}"
Width="{Binding Path=Width, ElementName=ProgressCell}"
Style="{StaticResource CustomProgressBar}" />
And my Progress-Bar style:
<Style x:Key="CustomProgressBar" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar" >
<Grid x:Name="Root">
<Border Name="PART_Track"
CornerRadius="0"
Background="{DynamicResource ProgressBackgroundColor}"
BorderBrush="{DynamicResource ProgressBackgroundColor}"
BorderThickness="1" />
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{DynamicResource ProgressBarFillColor}"
BorderBrush="{DynamicResource ProgressBarFillColor}"
BorderThickness="1"
HorizontalAlignment="Left" />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Value="False" Binding="{Binding IsChecked}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter TargetName="Root" Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="270" />
</Setter.Value>
</Setter>
<Setter TargetName="Root" Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>
<Setter TargetName="Root" Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So this is the things that currently not working:
When my Progress-Bar reach the value of 100% i want its Background color will change so i add this DataTrigger:
<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
So this not effect at all over my Pregress-Bar color when its reach 100%.
I even also try:
<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource Self}}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
When my View Model IsChecked property is set to false i want that my Progress-Bar Background color will change to Red - also this is not working.
I try to search many solutions but again and again same results - my Progress-Bar``color not changing at all.
EDIT:
<Style x:Key="CustomProgressBar2" TargetType="ProgressBar">
<Style.Triggers>
<Trigger Value="100" Property="Value">
<Setter Property="Background" Value="{DynamicResource ProgressBarFillCompleteColor}"/>
<Setter Property="Foreground" Value="Transparent"/>
</Trigger>
<DataTrigger Value="False" Binding="{Binding IsChecked}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar" >
<Grid x:Name="Root">
<Border Name="PART_Track"
CornerRadius="0"
Background="{DynamicResource ProgressBorderBrushColor}"
BorderBrush="{DynamicResource ProgressBorderBrushColor}"
BorderThickness="1" />
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Background}"
BorderThickness="1"
HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
First of all you need properly implement INotifyPropertyChanged interface.
public event PropertyChangedEventHandler PropertyChanged;
private int _Progress;
private int _Progress;
public int Progress
{
get {
return _Progress;
}
set
{
_Progress = value;
PropertyChanged(this, new PropertyChangedEventArgs("Progress"));
}
}
Then change your style. It will be better to use Style.Triggers instead
<Style.Triggers>
<Trigger Value="100" Property="Value">
<Setter Property="Background" Value="Green"/>
<Setter Property="Foreground" Value="Pink"/>
</Trigger>
<DataTrigger Value="False" Binding="{Binding IsChecked}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
And modify background binding on your barders inside template
<Border Name="PART_Track"
CornerRadius="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Background}"
BorderThickness="1" />
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{TemplateBinding Foreground}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="1"
HorizontalAlignment="Left" />
It will be enough to change Background when progress will be 100, but when progress will be more than 100 ( if you need it) foreground and background will be switched to default value. If you need to change color for progress >= 100 then you need ValueConverter instead of triggers.
EDIT:
Full solution.
<Window x:Class="WpfApplication3.ProgressWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication3"
mc:Ignorable="d"
Title="ProgressWindow" Height="200" Width="400">
<Window.Resources>
<SolidColorBrush x:Key="ProgressBarFillCompleteColor" Color="Green"/>
<SolidColorBrush x:Key="ProgressBorderBrushColor" Color="Gray"/>
<Style x:Key="CustomProgressBar" TargetType="ProgressBar">
<Setter Property="Foreground" Value="AliceBlue"/>
<Setter Property="Background" Value="{DynamicResource ProgressBorderBrushColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar" >
<Grid x:Name="Root">
<Border Name="PART_Track"
CornerRadius="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding Background}"
BorderThickness="1" />
<Border Name="PART_Indicator"
CornerRadius="0"
Background="{TemplateBinding Foreground}"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="1"
HorizontalAlignment="Left" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter TargetName="Root" Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="270" />
</Setter.Value>
</Setter>
<Setter TargetName="Root" Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>
<Setter TargetName="Root" Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Value="False" Binding="{Binding IsChecked}">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<Trigger Value="100" Property="Value">
<Setter Property="Background" Value="Green"/>
<Setter Property="Foreground" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<DockPanel>
<ProgressBar Name="progressBarColumn" DockPanel.Dock="Top" Height="20" Minimum="0" Maximum="100"
Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource CustomProgressBar}" />
<StackPanel>
<Button Content="Start" Click="Button_Click"/>
<CheckBox Content="Check me" IsChecked="{Binding IsChecked}"/>
</StackPanel>
</DockPanel>
</Window>
View and viewmodel
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for ProgressWindow.xaml
/// </summary>
public partial class ProgressWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ProgressWindow()
{
InitializeComponent();
DataContext = this;
}
private int _Progress;
public int Progress
{
get
{
return _Progress;
}
set
{
_Progress = value;
PropertyChanged(this, new PropertyChangedEventArgs("Progress"));
}
}
private bool _IsChecked;
public bool IsChecked
{
get
{
return _IsChecked;
}
set
{
_IsChecked = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
Progress = 0;
await Task.Run(async () =>
{
var value = 0;
while (value < 100)
{
await Task.Delay(500);
await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Progress += 10;
}));
}
});
}
}
}

How to set CornerRadius of a wpf button border via style and databinding

I have a simple WPF Button as under:-
<Button Height="150" Width="145" Canvas.Top="8" Canvas.Left="9" x:Name="cmdButton_Template" Background="{Binding Button_BackGround}" Style="{StaticResource MyLocalButton}" Mouse.PreviewMouseUp="cmdButton_Template_PreviewMouseUp" >
<Label>
<ContentControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Height="131" Canvas.Left="10" Canvas.Top="10" Width="142" >
<Canvas x:Name="ContentCanvas">
<TextBlock Canvas.Left="{Binding Text_2_Left,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Canvas.Top="{Binding Text_2_Top,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Text="{Binding Text, ElementName=txtItem_Cat_Name2,UpdateSourceTrigger=PropertyChanged}" FontSize="{Binding Font_Size_2}" FontFamily="{Binding Font_Name_2}" Foreground="{Binding Font_Color_2}" FontStyle="{Binding ElementName=chkItalic_2,Path=IsChecked,Converter={StaticResource FIC}, UpdateSourceTrigger=PropertyChanged}" TextDecorations="{Binding Font_Underline_2,Converter={StaticResource FUC}}" FontWeight="{Binding Font_Bold_2,Converter={StaticResource FVT}}" x:Name="Button_Text_2" MouseLeftButtonUp="Button_Text_2_MouseLeftButtonUp" Grid.RowSpan="3"/>
</Canvas>
</ContentControl>
</Label>
</Button>
and i have a style like this in userControl.Resources like this:
<UserControl.Resources>
<Style x:Key="MyLocalButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="borderZero" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}" CornerRadius="{Binding AllCorners,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SomeButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
This is my DataModel:
public class DM_ButtonSettings
{
public CornerRadius _AllCorners = new CornerRadius(10, 10, 10, 10);
public CornerRadius AllCorners
{
get { return _AllCorners; }
set
{
if (_AllCorners != value)
{
_AllCorners = value;
}
}
}
}
and this is my ViewModel:
public class DC_ButtonSettings:INotifyPropertyChanged
{
public CornerRadius _AllCorners = new CornerRadius(10, 10, 10, 10);
public CornerRadius AllCorners
{
get { return _AllCorners; }
set
{
if (_AllCorners != value)
{
_AllCorners = value;
RaisePropertyChangedEvent("AllCorners");
}
}
}
}
I have a ViewModel property named CornerRadius and i am trying to change the Radius of the button corners at runtime using that property by binding it to style in the local resoources of the user control.
I am passing an object of this ViewModel to the form where the Button lies,and am trying to change the Button corner radius by changing the CornerRadius programatically as per the program logic.Though the values in the ViewModel are getting changed,but the View is not getting updated.I know i am missing something very simple here,but am unable to figure out on my own.
How do i do it right?
I just removed your mode & updatesourcetrigger from the style. it's working for me.
<Style x:Key="MyLocalButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="borderZero" BorderThickness="2" BorderBrush="Black" Background="{TemplateBinding Background}" CornerRadius="{Binding AllCorners}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Adding a converter to Binding="{Binding}"

I have a DataGridColumnHeader Style that has a TextBox situated above the DataGridColumn. In the TextBox Style, there is a DataTrigger that sets its visibility based on the Text in the DataGridColumn. Rather than checking if its value equals "Pos", I would like to use a converter to see if its value begins with the string "Pos". But when I add the converter, the value parameter in the converter turns out not being a string. Instead it is the MainWindow object that the datagrid belongs to. Why would it take on a different meaning when I add a converter?
<Style TargetType="{x:Type DataGridColumnHeader}" x:Key="DataGridColumnHeaderStyle"
xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<Style.Resources>
<SolidColorBrush x:Key="borderBackground">#E4E5ED</SolidColorBrush>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Border Background="{StaticResource borderBackground}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Margin="1" Grid.Column="0" Grid.Row="0" IsReadOnly="True"
Text="{Binding Path=DataContext.TotalPos, StringFormat=N0, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="Pos">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<theme:DataGridHeaderBorder Grid.Column="0" Grid.Row="1" SortDirection="{TemplateBinding SortDirection}"
IsHovered="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
IsClickable="{TemplateBinding CanUserSort}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding ="{TemplateBinding Padding}"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<TextBlock Grid.Column="0" Grid.Row="1" Text="{TemplateBinding Content}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
TextWrapping="Wrap"></TextBlock>
</theme:DataGridHeaderBorder>
<Thumb Grid.Column="0" Grid.Row="1" Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Thumb Grid.Column="0" Grid.Row="1" Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With converter:
<src:StartsWith x:Key="startsWith"/>
...
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource startsWith}, ConverterParameter=Pos}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
...
[ValueConversion(typeof(string), typeof(bool))]
public class StartsWith : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((string)value).StartsWith((string)parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("Not Implemented.");
}
}
It doesn't know what to bind to...add Binding RelativeSource={RelativeSource Self}, Path=Text for the converter.
I bind with this, thanks
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridColumnHeader, AncestorLevel=1}, Path=Column.Header, Converter={StaticResource startsWith}, ConverterParameter=Pos}" Value="True">

Resources