C# 使标准属性与DependencyProperty一起更新

C# 使标准属性与DependencyProperty一起更新,c#,wpf,binding,properties,dependencies,C#,Wpf,Binding,Properties,Dependencies,我可能对此完全不感兴趣,但我发誓我记得我在什么地方读过如何做到这一点,我就是找不到它。我有一个dependencPropertyMinutes作为TimePicker自定义控件的一部分。它的数据类型是int,因为这是使增加/减少按钮工作的唯一方法。问题是1-9的分钟数显示时没有前导零。为了避免这种情况,我添加了一个标准属性MinuteZeros,它将Minutes的值转换为string,并使用ToString(“00”)。此属性已绑定到显示内容。现在,当我点击增加/减少按钮时,它不会更新。如何绑

我可能对此完全不感兴趣,但我发誓我记得我在什么地方读过如何做到这一点,我就是找不到它。我有一个dependencProperty
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-无效,请参阅

选项2:使用StringFormatConverter-它可以工作

摆脱Minutezero,使用

<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
}

{绑定
RelativeSource={RelativeSource TemplatedParent},
路径=分钟,
StringFormatConverter={StaticResource StringFormatConverter},
转换器参数=D2
}
公共类StringFormatConverter:IValueConverter
{
#IValueConverter的区域实现
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
如果(值==null)
{
抛出新的ArgumentNullException(“值”);
}
var fmt=string.Format(“{{0:{0}}}”,参数);
返回string.Format(fmt,value);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的NotImplementedException();
}
#端区
}
选项3:我还没有实现


将逻辑放入OnHourChanged和OnMinuteChanged处理程序中,以同步分钟和分钟零。

只是想发布最终的更改,从而使这项工作正常进行

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

这有帮助吗?如果我完全按照您的方式操作(
Path=MinuteZeros
),它会显示两位数字,但增加/减少按钮不会执行任何操作。如果我将其切换到(
Path=Minutes
),则增加/减少有效,但不会同时显示两个零。