Changing source of an Image inside of a Button template - c#

I have a button with an image defined in XAML like this:
<Button x:Name="buttonTest">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image x:Name="imageTest" Width="57" Height="81" Source="/Images/sample.png" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
How can I change the source of the image when the button is clicked?

I would probably do this with a toggle button instead of button since it has the IsChecked property that you can base the image switch on.
First you'll need some converter to go from true/false to the image path, may as well make it a generic one that you can use over and over, add this to your project and setup an xmlns to point to it in your xaml.
public class BooleanSwitchConverter : DependencyObject, IValueConverter
{
public object TrueValue
{
get { return (object)GetValue(TrueValueProperty); }
set { SetValue(TrueValueProperty, value); }
}
public static readonly DependencyProperty TrueValueProperty =
DependencyProperty.Register("TrueValue", typeof(object), typeof(BooleanSwitchConverter), new PropertyMetadata(null));
public object FalseValue
{
get { return (object)GetValue(FalseValueProperty); }
set { SetValue(FalseValueProperty, value); }
}
public static readonly DependencyProperty FalseValueProperty =
DependencyProperty.Register("FalseValue", typeof(object), typeof(BooleanSwitchConverter), new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((bool)value) ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then replace your Button with a toggle button like this using a Binding on IsChecked to pick the image.
<ToggleButton>
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Border>
<Image>
<Image.Source>
<Binding Path="IsChecked" RelativeSource="{RelativeSource TemplatedParent}">
<Binding.Converter>
<local:BooleanSwitchConverter
TrueValue="1.jpg"
FalseValue="2.jpg"/>
</Binding.Converter>
</Binding>
</Image.Source>
</Image>
</Border>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>

You can use a trigger like this (Used a rectangle for simplicity in the sample):
<Button x:Name="buttonTest" Width="200" Height="200">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" >
<Rectangle x:Name="Image" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" Fill="Yellow"></Rectangle>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Image" Property="Fill" Value="Red"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>

So I finally figured it out, user Gambi provided an answer in another thread.

Related

DatePicker Template, Binding to SelectedDate not Working

I'm trying to change the DatePicker template. I almost made the design with the help of Custom Control. But not only did I spend 2 days of my life on this, it also does not work incorrectly. The SelectedDateChenged call change event is called multiple times. I decided to change the approach, rewrite the template. Now there was a problem that Binding does not work. That is, there are changes in the calendar. I see them, the event is called, the SelectedDate changes there, but the Binding does not work. Please help me figure it out, I'm attaching the source code of the template and converters.
DatePicker Template
<Style x:Key="DatePickerStyle" TargetType="{x:Type DatePicker}">
<Style.Resources>
<conv:MonthToGenitiveMonthNameConverter x:Key="MonthToGenitiveMonthNameConverter"/>
<conv:MonthToAbbreviatedMonthNameConverter x:Key="MonthToAbbreviatedMonthNameConverter"/>
<conv:DayToDayNameConverter x:Key="DayToDayNameConverter"/>
<conv:DateToTwoDigitDateConverter x:Key="DateToTwoDigitDateConverter"/>
</Style.Resources>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Height" Value="70"/>
<Setter Property="Width" Value="500"/>
<Setter Property="IsTodayHighlighted" Value="True"/>
<Setter Property="SelectedDateFormat" Value="Short"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePicker}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<Grid x:Name="PART_Root" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="{Binding Path=SelectedDate.Day, Converter={StaticResource DateToTwoDigitDateConverter}}" />
<StackPanel Margin="10,2,0,2" VerticalAlignment="Center" >
<TextBlock Foreground="{TemplateBinding Foreground}" FontSize="24" FontWeight="Bold" Text="{Binding Path=SelectedDate.Month, Converter={StaticResource MonthToGenitiveMonthNameConverter}}"/>
<TextBlock Foreground="{TemplateBinding Foreground}" FontSize="14" Text="{Binding Path=SelectedDate.DayOfWeek, Converter={StaticResource DayToDayNameConverter}}"/>
</StackPanel>
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="{Binding Path=SelectedDate.Year}" />
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding Foreground}" FontSize="50" Text="г." />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="PART_Button" Style="{StaticResource ExtendedDataPickerButtonStyle}">
<fa:IconImage Icon="Calendar" Style="{StaticResource BigIconStyle}"/>
</Button>
<DatePickerTextBox x:Name="PART_TextBox" Visibility="Collapsed"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_Button}" StaysOpen="False"
ui:PopupProperties.HorizontalPlacementAlignment="Center"
ui:PopupProperties.VerticalOffset="2"/>
</StackPanel>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Converters
[ValueConversion(typeof(string), typeof(int))]
class DateToTwoDigitDateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int val = (int)value;
if (((int)val / 10) > 0)
{
return value.ToString();
}
else
{
return "0" + value.ToString();
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(string), typeof(DayOfWeek))]
class DayToDayNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return culture.DateTimeFormat.GetDayName((DayOfWeek)value).FirstCharToUpper();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(string), typeof(int))]
class MonthToAbbreviatedMonthNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return culture.DateTimeFormat.GetAbbreviatedMonthName((int)value).FirstCharToUpper();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(string), typeof(int))]
class MonthToGenitiveMonthNameConverter : IValueConverter
{
private const int ArrayZeroBasedConst = 1;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return culture.DateTimeFormat.MonthGenitiveNames[(int)value - ArrayZeroBasedConst].FirstCharToUpper();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(string), typeof(int))]
class MonthToNominativeMonthNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return culture.DateTimeFormat.GetMonthName((int)value).FirstCharToUpper();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I don't know what to try anymore.
The code from this site, for which many thanks, I have already checked, just in case, it's not in it.
ui:PopupProperties.HorizontalPlacementAlignment="Center"
ui:PopupProperties.VerticalOffset="2"
I am trying to remake DatePicker and Calendar. I don't have access to the Internal methods in the source code, and there are quite a few of them. I can publish the source codes of the last iteration of programming, but it turned out to be a very large heap with truncated functionality.
I still solved this problem. I will not publish the entire code, I will publish only significant changes.
Firstly, Custom Control appeared again, only very minimalistic.
public class ModernDatePicker : DatePicker, IDisposable
{
public static readonly DependencyProperty VisualizatedDateProperty = DependencyProperty.Register(nameof(VisualizatedDate), typeof(DateTime), typeof(ModernDatePicker),
new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public DateTime VisualizatedDate
{
get { return (DateTime)GetValue(VisualizatedDateProperty); }
set { SetValue(VisualizatedDateProperty, value); }
}
static ModernDatePicker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ModernDatePicker), new FrameworkPropertyMetadata(typeof(ModernDatePicker)));
}
public ModernDatePicker()
{
Loaded += ModernDatePicker_Loaded;
SelectedDateChanged += ModernDatePicker_SelectedDateChanged;
}
private void ModernDatePicker_Loaded(object sender, RoutedEventArgs e)
{
if (this.SelectedDate == null)
{
SelectedDate = VisualizatedDate;
}
}
private void ModernDatePicker_SelectedDateChanged(object? sender, SelectionChangedEventArgs e)
{
ModernDatePicker mdp = (ModernDatePicker)sender;
if (mdp.SelectedDate != null)
{
VisualizatedDate = mdp.SelectedDate.Value;
}
}
}
public void Dispose()
{
SelectedDateChanged -= ModernDatePicker_SelectedDateChanged;
Loaded -= ModernDatePicker_Loaded;
}
SelectDate is a DateTime? type, which does not allow you to get the value immediately at startup, you had to use a DependencyProperty, with a DateTime type, in order to be able to use Binding.
Secondly, changes in XAML.
<Style TargetType="{x:Type cc:ModernDatePicker}">
<Style.Resources>
<conv:MonthToGenitiveMonthNameConverter x:Key="MonthToGenitiveMonthNameConverter"/>
<conv:DayToDayNameConverter x:Key="DayToDayNameConverter"/>
<conv:DateToTwoDigitDateConverter x:Key="DateToTwoDigitDateConverter"/>
</Style.Resources>
<Setter Property="Foreground" Value="#223266"/>
<Setter Property="IsTodayHighlighted" Value="True"/>
<Setter Property="CalendarStyle" Value="{DynamicResource ModernCalendarStyle}"/>
<Setter Property="SelectedDateFormat" Value="Short"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="SubForeground" Value="#9eabe2"/>
<Setter Property="OtherForeground" Value="White"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:ModernDatePicker}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<Grid x:Name="PART_Root" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding OtherForeground}" FontSize="50" Text="{Binding VisualizatedDate.Day, RelativeSource={RelativeSource AncestorType={x:Type cc:ModernDatePicker}},Converter = {StaticResource DateToTwoDigitDateConverter}}" />
<StackPanel Margin="10,2,0,2" VerticalAlignment="Center" >
<TextBlock Foreground="{TemplateBinding OtherForeground}" FontSize="24" FontWeight="Bold" Text="{Binding VisualizatedDate.Month, RelativeSource={RelativeSource AncestorType={x:Type cc:ModernDatePicker}}, Converter={StaticResource MonthToGenitiveMonthNameConverter}}"/>
<TextBlock Foreground="{TemplateBinding SubForeground}" FontSize="14" Text="{Binding VisualizatedDate.DayOfWeek, RelativeSource={RelativeSource AncestorType={x:Type cc:ModernDatePicker}}, Converter={StaticResource DayToDayNameConverter}}"/>
</StackPanel>
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding OtherForeground}" FontSize="50" Text="{Binding VisualizatedDate.Year, RelativeSource={RelativeSource AncestorType={x:Type cc:ModernDatePicker}}}" />
<TextBlock Margin="5 0 0 0" Foreground="{TemplateBinding OtherForeground}" FontSize="50" Text="г." />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="PART_Button" Style="{StaticResource ExtendedDataPickerButtonStyle}">
<fa:IconImage Icon="Calendar" Style="{StaticResource BigIconStyle}"/>
</Button>
<DatePickerTextBox x:Name="PART_TextBox" Visibility="Collapsed"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_Button}" StaysOpen="False"
ui:PopupProperties.HorizontalPlacementAlignment="Center"
ui:PopupProperties.VerticalOffset="2"/>
</StackPanel>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
Well, in fact, by analogy

Access element from style WPF

I have a style declared in a ResourceDictionary like so.
<Style x:Key="MapMarkerLabelStyle" TargetType="{x:Type TextBlock}">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="{Binding ActualWidth,
Converter={StaticResource DoubleMultiplierConverter},
ConverterParameter=-0.5}"
Y="-62"></TranslateTransform>
</Setter.Value>
</Setter>
</Style>
And the textblock
<TextBlock Style="{StaticResource MapMarkerLabelStyle}" />
And the converter:
public class DoubleMultiplierConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var originalValue = (double) value;
var format = new NumberFormatInfo {NumberDecimalSeparator = "."};
var multiplier = System.Convert.ToDouble(parameter, format);
return originalValue * multiplier;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
In the translate transform i need to access the textblock ActualWidth property but cant figure out how the binding should look.
The Binding is missing an appropriate source object. To bind to the TextBlock's ActualWidth property, you should set the RelativeSource like this:
<Style x:Key="MapMarkerLabelStyle" TargetType="TextBlock">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform
X="{Binding Path=ActualWidth,
RelativeSource={RelativeSource AncestorType=TextBlock}
Converter={StaticResource DoubleMultiplierConverter},
ConverterParameter=-0.5}"
Y="-62"/>
</Setter.Value>
</Setter>
</Style>
Try this.
<TranslateTransform X="{Binding RelativeSource={RelativeSource Self},
Path=ActualWidth,
Converter={StaticResource DoubleMultiplierConverter},
ConverterParameter=-0.5}"
Y="-62">
</TranslateTransform>

Binding fails when using SolidColorBrush resource on Stroke property

I have created a UserControl and have quite a few bindings to several custom DependencyProperties in the control. For some reason though, one of these is failing with the error:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'ElementName=YearSelectorControl'.
BindingExpression:Path=SelectedBorderColor; DataItem=null; target
element is 'SolidColorBrush' (HashCode=45568629); target property is
'Color' (type 'Color')
The control includes a ToggleButton and Popup. The error occurs when the Popup is opened by clicking on the ToggleButton.
Here is the xaml:
<UserControl x:Class="MyProject.Views.YearSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyProject.Views"
mc:Ignorable="d"
d:DesignHeight="23" d:DesignWidth="181"
x:Name="YearSelectorControl">
<UserControl.Resources>
<SolidColorBrush x:Key="HoverColorBrush" Color="{Binding ElementName=YearSelectorControl, Path=HoverColor}"/> <!--This binding is virtually identical, but works fine-->
<SolidColorBrush x:Key="SelectedBorderColorBrush" Color="{Binding ElementName=YearSelectorControl, Path=SelectedBorderColor}"/> <!--This is the binding that fails-->
<local:YearToBackColorConverter x:Key="YearToBackColorConverter"/>
<local:YearToBorderThicknessConverter x:Key="YearToBorderThicknessConverter"/>
<Style x:Key="ForwardBackButtons" TargetType="{x:Type Button}" >
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontFamily" Value="Arial" />
</Style>
<ControlTemplate x:Key="YearButton" TargetType="{x:Type Button}">
<Grid Width="55" Height="30" Margin="2">
<Rectangle x:Name="ButtonRectangle" Stroke="{StaticResource SelectedBorderColorBrush}"> <!--Use of the failing brush-->
<!--Removed code that determines StrokeThickness. Works correctly if Stroke set to a specific color rather than a Static Resource-->
</Rectangle>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonRectangle" Property="Fill" Value="{StaticResource HoverColorBrush}"/> <!--Use of the properly binding brush-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<!--Layout here-->
</Grid>
</UserControl>
Here is an excerpt from the code-behind for the two DependencyProperties that are bound to SolidColorBrush resources:
public Color HoverColor
{
get { return (Color)GetValue(HoverColorProperty); }
set { SetValue(HoverColorProperty, value); }
}
public static readonly DependencyProperty HoverColorProperty =
DependencyProperty.Register("HoverColor", typeof(Color), typeof(YearSelector), new PropertyMetadata(Color.FromArgb(255,190,230,253)));
public Color SelectedBorderColor
{
get { return (Color)GetValue(SelectedBorderColorProperty); }
set { SetValue(SelectedBorderColorProperty, value); }
}
public static readonly DependencyProperty SelectedBorderColorProperty =
DependencyProperty.Register("SelectedBorderColor", typeof(Color), typeof(YearSelector), new PropertyMetadata(Color.FromArgb(255,126,0,234)));
I went away from this for a few months to focus on more important elements of my application and have finally come back to it. I discovered the solution, though I'm not sure why it was a problem in the first place.
For whatever reason, binding a SolidColorBrush resource to the Stroke property doesn't work. What I did instead, is I bound the Color DependencyProperty directly to Stroke and used an IValueConverter to convert it to a SolidColorBrush.
XAML:
<Rectangle x:Name="ButtonRectangle" Stroke="{Binding ElementName=YearSelectorControl, Path=SelectedBorderColor, Converter={StaticResource ColorToSolidColorBrushConverter}}">
Code-behind:
public class ColorToSolidColorBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
Color c = (Color)value;
return new SolidColorBrush(c);
}
catch
{
return new SolidColorBrush(Color.FromRgb(0,0,0));
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

WPF TemplateBinding Concatenate String for Value

I want to add a Custom Property (via a Dependency Property) to my custom ToggleButton Template.
Now i want to have the value of the containing Label (as a placeholder for future implementation) to be a concatenated value of, say "Hello " and the actual Property Value.
Without the concatenation it works fine (displaying "Warrior" on the Label)
But when i try to set the label as a concatenation the xaml doesnt compile anymore.
<Label Content="Hello {TemplateBinding local:HeroClassCheckbox.HeroClass}"/>
How can i achieve this?
The Rest of the Code:
My .xaml
<Window.Resources>
<ResourceDictionary>
<Style x:Key="HeroClassCheckbox" TargetType="ToggleButton">
<Setter Property="Content" Value="Green" />
<Setter Property="local:HeroClassCheckbox.HeroClass" Value="NoClass"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Label Content="{TemplateBinding local:HeroClassCheckbox.HeroClass}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ToggleButton Width="150" Height="50" local:HeroClassCheckbox.HeroClass="Warrior" Style="{DynamicResource HeroClassCheckbox}"/>
</Grid>
My .xaml.cs
public static class HeroClassCheckbox
{
public static readonly DependencyProperty HeroClassProperty = DependencyProperty.RegisterAttached("HeroClass",
typeof(string), typeof(HeroClassCheckbox), new FrameworkPropertyMetadata(null));
public static string GetHeroClass(UIElement element)
{
if (element == null)
throw new ArgumentNullException("element");
return (string)element.GetValue(HeroClassProperty);
}
public static void SetHeroClass(UIElement element, string value)
{
if (element == null)
throw new ArgumentNullException("element");
element.SetValue(HeroClassProperty, value);
}
}
You should use a converter as an approach to your goal. Here is an example..
public class HelloLabelConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
char[] removeThis = "Hello ".ToCharArray();
return value.ToString().TrimStart(removeThis);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return string.Format("Hello {0}", value);
}
}
<Window.Resources>
<local:HelloLabelConverter x:Key="HelloLabelConverter" />
</Window.Resources>
<Grid>
<Label Content="{Binding ElementName= lblPropertyToBind, Path=Text, Converter={StaticResource HelloLabelConverter}}"></Label>
</Grid>

Bind DependencyProperty in style

I'm sure this is a simple thing to do, and to look up, but I've yet to have any luck. Basically I want to style a WPF Slider such that when used I can give it two additional strings to display.
The new control looks like this:
public class SliderPicker : Slider
{
public string LeftLabel
{
get { return (string)GetValue(LeftLabelProperty); }
set { SetValue(LeftLabelProperty, value); }
}
public static readonly DependencyProperty LeftLabelProperty =
DependencyProperty.Register("LeftLabel", typeof(string), typeof(SliderPicker), new UIPropertyMetadata(String.Empty));
public string RightLabel
{
get { return (string)GetValue(RightLabelProperty); }
set { SetValue(RightLabelProperty, value); }
}
public static readonly DependencyProperty RightLabelProperty =
DependencyProperty.Register("RightLabel", typeof(string), typeof(SliderPicker), new UIPropertyMetadata(String.Empty));
}
The style like this:
<Style x:Key="SlickSlider" TargetType="{x:Type Slider}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Slider}">
...
<TextBlock Text="{TemplateBinding LeftLabel}" Grid.Row="2" HorizontalAlignment="Left" />
<TextBlock Text="{TemplateBinding RightLabel}" Grid.Row="2" HorizontalAlignment="Right" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And usage:
<controls:SliderPicker LeftLabel="RealPreference" RightLabel="RealCoverage" Width="400" Style="{StaticResource SlickSlider}"/>
This doesn't seem to work. So, how do I set the DP on the control and show it in the template? I thought that's what TemplateBinding was for?
You only need a small fix. Change {x:Type Slider} to {x:Type controls:SliderPicker}
You need to apply the custom control as the type in your style and template. Without it your trying to look for LeftLabelProperty and RightLabelProperty in Slider and not SliderPicker with your template binding.
Change your style to
<Style x:Key="SlickSlider" TargetType="{x:Type controls:SliderPicker}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:SliderPicker}">
...
<TextBlock Text="{TemplateBinding LeftLabel}" Grid.Row="2" HorizontalAlignment="Left" />
<TextBlock Text="{TemplateBinding RightLabel}" Grid.Row="2" HorizontalAlignment="Right" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Have tried this with the class you've posted and it works fine :)

Categories

Resources