使用DependencyProperty进行标准属性更新

时间:2012-03-16 21:33:39

标签: c# wpf binding properties dependencies

我可能完全偏离这一点,但我发誓我记得在某处读到如何做到这一点,我似乎无法找到它。我有一个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>

2 个答案:

答案 0 :(得分:1)

选项1:使用StringFormat - 不起作用,请参阅SO article

选项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。

答案 1 :(得分:0)

只想发布使这项工作有效的最终更改。

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