有关用户控件中DependencyProperty的setter中的代码的问题

时间:2015-12-20 11:13:30

标签: c# xaml user-controls winrt-xaml dependency-properties

我在页面上显示时间/时钟作为用户控件(ClockControl),实际时间模型来自另一个类的DateTime对象(ClockTime )。我在ClockControl上有2个文本块:

  1. Textblock' Second_update_by_binding'绑定到依赖属性' Second_binded'反过来,它必然会模拟ClockTime' Second'

  2. Textblock' Second_update_by_manipulating'通过操纵模型ClockTime' Second'的值来更新所以它增加了' 0'在前面如果' Second'只有1位数(或少于10位)

  3. 无论是最好的方法,我都能实现我的目标。但是,我遇到了一些问题,我不太明白为什么会这样。特别是,它是我最困惑的时钟用户控件中依赖属性内的getter / setter内部代码背后的逻辑。

    MainPage.xaml中:

    <Page x:Class="App1.MainPage" ...">
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <local:ClockControl x:Name="useControl" 
                   Second_binded="{Binding Second}" 
                   Second_manipulated="{Binding Second}"  />
        </Grid>
    </Page>
    

    MainPage.cs:

    public sealed partial class MainPage : Page
    {
        ClockTime clock;
        DispatcherTimer Timer;
    
        public MainPage()
        {
            clock = new ClockTime();
            this.InitializeComponent();
            this.DataContext = clock;
              // I am adding this DispatchTimer to force the update of the text 
              // 'Second_update_by_manipulating' on the ClockControl since the
              // Binding of Second_manipulated doesnt work
            Timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 1) };
            Timer.Tick += Timer_Tick;
            Timer.Start();
        }
    
        private void Timer_Tick(object sender, object e)
        {
            useControl.Second_manipulated = clock.Second.ToString();
        }
    }
    

    ClockTime模型:

    class ClockTime : INotifyPropertyChanged
    {
        public ClockTime()
        {
            var Timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 1) };
            Timer.Tick += Timer_Tick;
            Timer.Start();
        }
    
        private void Timer_Tick(object sender, object e)
        {
            Second = DateTime.Now.Second;
        }
    
        //===================================================
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        //===================================================
        private int _second;
        public int Second
        {
            get { return this._second; }
            set
            {
                if (value != this._second)
                {
                    this._second = value;
                    NotifyPropertyChanged("Second");
                }
            }
        }
    }
    

    ClockControl.xaml:

    <UserControl x:Class="App1.ClockControl" ...>
        <Grid>
            <StackPanel>
                <TextBlock x:Name="Second_update_by_manipulating"  />
                <TextBlock x:Name="Second_update_by_binding" Text="{Binding Second_binded}" />
            </StackPanel>
        </Grid>
    </UserControl>
    

    ClockControl.cs:

    public sealed partial class ClockControl : UserControl
    {
        public ClockControl()
        {
            this.InitializeComponent();
            (this.Content as FrameworkElement).DataContext = this;
        }
        //==================================
        public String Second_binded
        {
            get {
                return (String)GetValue(Second_bindedProperty); 
            }
            set {
                Debug.WriteLine(" in Second_binded ");
                SetValue(Second_bindedProperty, value);
            }
        }
        public static readonly DependencyProperty Second_bindedProperty =
            DependencyProperty.Register(
            "Second_binded", 
            typeof(string),
            typeof(ClockControl), 
            new PropertyMetadata(""));
        //==================================
        public String Second_manipulated
        {
            get
            {
                return (String)GetValue(Second_manipulatedProperty);
            }
            set
            {
                Second_update_by_manipulating.Text = (Convert.ToInt32(value)<10) ? "0"+value : value;
                Debug.WriteLine(" in Second_manipulated ");
                SetValue(Second_manipulatedProperty, value);
            }
        }
        public static readonly DependencyProperty Second_manipulatedProperty =
            DependencyProperty.Register(
            "Second_manipulated",
            typeof(string),
            typeof(ClockControl),
            new PropertyMetadata(""));
        //==================================
    }
    

    所以这是我的问题:

    1. 为什么调试代码 Debug.WriteLine(&#34;在Second_binded&#34;中); 在ClockControl中的Second_binded依赖属性的setter中,从不调用&#39 ;二&#39;在模型ClockTime正在更新。

    2. 调用ClockControl中Second_manipulated依赖属性的setter中的代码 Debug.WriteLine(&#34;在Second_manipulated&#34;中); ,并且代码 Value_1。 Text =(Convert.ToInt32(value)&lt; 10)? &#34; 0&#34; + value:value; 执行以更改ClockControl上的文本,但只有在MainPage.cs中添加另一个DispatchTimer以强制代码 useControl.Second_manipulated后才能执行此操作= clock.Second.ToString(); 更新时间。为什么我必须以这种方式更新Second_manipulated,即使我已经在MainPage.xaml中将Second_manipulated绑定为Second?

    3. 非常欢迎任何能够启发我对C#的了解的想法和评论。

      感谢

1 个答案:

答案 0 :(得分:1)

如果要跟踪DependencyProperty中的更改,则必须注册PropertyChangedCallback处理程序。更新绑定的值时,系统不会触发属性设置器。

public static readonly DependencyProperty Second_bindedProperty =
        DependencyProperty.Register(
        "Second_binded",
        typeof(string),
        typeof(ClockControl),
        new PropertyMetadata("", PropertyChangedCallback));

private static void PropertyChangedCallback(DependencyObject dependencyObject,
             DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    Debug.WriteLine(" in Second_binded callback");
}

你的setter在第二个属性中命中的原因是因为你自己用useControl.Second_manipulated = clock.Second.ToString();强制它,这不是使用绑定的正确方法。