将标准属性与DependencyProperty一起更新
本文关键字:一起 更新 DependencyProperty 标准 属性 | 更新日期: 2023-09-27 18:28:08
我可能对此完全不感兴趣,但我发誓我记得在某个地方读过如何做到这一点,我似乎找不到它。我有一个DependencyProperty Minutes
作为TimePicker自定义控件的一部分。它的数据类型是int
,因为这是使增加/减少按钮工作的唯一方法。这样做的问题是,从1-9开始的分钟显示没有前导零。为了避免这种情况,我添加了一个标准属性MinuteZeros
,它将Minutes
的值转换为string
并使用ToString("00")
。此属性绑定到显示内容。现在,当我点击增加/减少按钮时,它不会更新。如何绑定Minutes
和MinuteZeros
,使它们自动更新?
代码:
public class TimePicker : Control
{
public static DependencyProperty HourProperty = DependencyProperty.Register("Hour", typeof(int), typeof(TimePicker),
new FrameworkPropertyMetadata((int)12, new PropertyChangedCallback(OnHourChanged)));
public static DependencyProperty MinuteProperty = DependencyProperty.Register("Minute", typeof(int), typeof(TimePicker),
new FrameworkPropertyMetadata((int)00, new PropertyChangedCallback(OnMinuteChanged)));
public int Hour
{
get { return (int)GetValue(HourProperty); }
set { SetValue(HourProperty, value); }
}
public string MinuteZeros
{
get { return Minute.ToString("00"); }
set { value = Minute.ToString("00"); }
}
public int Minute
{
get { return (int)GetValue(MinuteProperty); }
set { SetValue(MinuteProperty, value); }
}
#endregion
#region Events
public override void OnApplyTemplate()
{
var upButton = GetTemplateChild("PART_IncreaseTime") as RepeatButton;
upButton.Click += IncreaseClick;
var downButton = GetTemplateChild("PART_DecreaseTime") as RepeatButton;
downButton.Click += DecreaseClick;
var hourButton = GetTemplateChild("PART_Hour") as ToggleButton;
hourButton.Checked += HourSelected;
var minuteButton = GetTemplateChild("PART_Minute") as ToggleButton;
minuteButton.Checked += MinuteSelected;
}
private void HourSelected(object sender, RoutedEventArgs e)
{
var minuteButton = GetTemplateChild("PART_Minute") as ToggleButton;
minuteButton.IsChecked = false;
}
private void MinuteSelected(object sender, RoutedEventArgs e)
{
var hourButton = GetTemplateChild("PART_Hour") as ToggleButton;
hourButton.IsChecked = false;
}
private void IncreaseClick(object sender, RoutedEventArgs e)
{
var hourButton = GetTemplateChild("PART_Hour") as ToggleButton;
var minuteButton = GetTemplateChild("PART_Minute") as ToggleButton;
if (hourButton.IsChecked == true)
{
if (Hour == 12)
{
Hour = 1;
}
else
{
Hour += 1;
}
}
else if (minuteButton.IsChecked == true)
{
if (Minute == 59)
{
Minute = 00;
}
else
{
Minute += 1;
}
}
}
private void DecreaseClick(object sender, RoutedEventArgs e)
{
var hourButton = GetTemplateChild("PART_Hour") as ToggleButton;
var minuteButton = GetTemplateChild("PART_Minute") as ToggleButton;
if (hourButton.IsChecked == true)
{
if (Hour == 1)
{
Hour = 12;
}
else
{
Hour -= 1;
}
}
else if (minuteButton.IsChecked == true)
{
if (Minute == 00)
{
Minute = 59;
}
else
{
Minute -= 1;
}
}
}
private static void OnHourChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
}
private static void OnMinuteChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
}
static TimePicker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(typeof(TimePicker)));
}
}
public partial class TimePickerEvents : ResourceDictionary
{
TimePicker time = new TimePicker();
void PART_IncreaseTime_Click(object sender, RoutedEventArgs e)
{
time.Hour += 1;
}
}
XAML:
<ToggleButton x:Name="PART_Minute"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Margin="0"
MinWidth="25"
BorderBrush="Transparent"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MinuteZeros}">
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ContentPresenter x:Name="ContentPart"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.Foreground="#FF605c" Visibility="Collapsed">
<ContentPresenter.Effect>
<BlurEffect />
</ContentPresenter.Effect>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ContentPart" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="ContentPart" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Transparent" />
</Style>
</ToggleButton.Style>
</ToggleButton>
选项1:使用StringFormat-不起作用,请参阅SO文章
选项2:使用StringFormatConverter-它确实可以
摆脱MinuteZeros并使用
<Converters:StringFormatConverter x:Key="StringFormatConverter" />
{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=Minutes,
StringFormatConverter={StaticResource StringFormatConverter},
ConverterParameter=D2
}
public class StringFormatConverter : IValueConverter
{
#region Implementation of IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
var fmt = string.Format("{{0:{0}}}", parameter);
return string.Format(fmt, value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
选项3:我还没有实现
在OnHourChanged和OnMinuteChanged处理程序中放入逻辑,以同步Minutes和MinutesZeros。
只是想发布使这项工作成功的最终更改。
public static DependencyProperty SelectedTimeProperty = DependencyProperty.Register("SelectedTime", typeof(TimeSpan), typeof(TimePicker),
new FrameworkPropertyMetadata((TimeSpan.Zero), new PropertyChangedCallback(OnSelectedTimeChanged)));
public TimeSpan SelectedTime
{
get { return (TimeSpan)GetValue(SelectedTimeProperty); }
set { SetValue(SelectedTimeProperty, value); }
}
private static void OnHourChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
TimePicker tp = (TimePicker)sender;
//TimePicker tp = new TimePicker();
var amButton = tp.GetTemplateChild("PART_AmIndicator") as RadioButton;
var pmButton = tp.GetTemplateChild("PART_PmIndicator") as RadioButton;
if (pmButton.IsChecked != false)
{
tp.SelectedTime = new TimeSpan((int.Parse(tp.Hour) + 12), int.Parse(tp.Minute), 0);
}
else if (amButton.IsChecked != false && (tp.Hour == "12"))
{
tp.SelectedTime = new TimeSpan(0, int.Parse(tp.Minute), 0);
}
else
{
tp.SelectedTime = new TimeSpan(int.Parse(tp.Hour), int.Parse(tp.Minute), 0);
}
}
private static void OnMinuteChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//TimePicker tp = new TimePicker();
TimePicker tp = (TimePicker)sender;
var amButton = tp.GetTemplateChild("PART_AmIndicator") as RadioButton;
var pmButton = tp.GetTemplateChild("PART_PmIndicator") as RadioButton;
if (pmButton.IsChecked != false)
{
tp.SelectedTime = new TimeSpan((int.Parse(tp.Hour) + 12), int.Parse(tp.Minute), 0);
}
else if (amButton.IsChecked != false && (tp.Hour == "12"))
{
tp.SelectedTime = new TimeSpan(0, int.Parse(tp.Minute), 0);
}
else
{
tp.SelectedTime = new TimeSpan(int.Parse(tp.Hour), int.Parse(tp.Minute), 0);
}
}