将标准属性与DependencyProperty一起更新

本文关键字:一起 更新 DependencyProperty 标准 属性 | 更新日期: 2023-09-27 18:28:08

我可能对此完全不感兴趣,但我发誓我记得在某个地方读过如何做到这一点,我似乎找不到它。我有一个DependencyProperty Minutes作为TimePicker自定义控件的一部分。它的数据类型是int,因为这是使增加/减少按钮工作的唯一方法。这样做的问题是,从1-9开始的分钟显示没有前导零。为了避免这种情况,我添加了一个标准属性MinuteZeros,它将Minutes的值转换为string并使用ToString("00")。此属性绑定到显示内容。现在,当我点击增加/减少按钮时,它不会更新。如何绑定MinutesMinuteZeros,使它们自动更新?

代码:

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>

将标准属性与DependencyProperty一起更新

选项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);
        }
    }