我在页面上显示时间/时钟作为用户控件(ClockControl
),实际时间模型来自另一个类的DateTime
对象(ClockTime
)。我在ClockControl
上有2个文本块:
Textblock' Second_update_by_binding'绑定到依赖属性' Second_binded'反过来,它必然会模拟ClockTime' Second'
Textblock' Second_update_by_manipulating'通过操纵模型ClockTime' Second'的值来更新所以它增加了' 0'在前面如果' Second'只有1位数(或少于10位)
无论是最好的方法,我都能实现我的目标。但是,我遇到了一些问题,我不太明白为什么会这样。特别是,它是我最困惑的时钟用户控件中依赖属性内的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(""));
//==================================
}
所以这是我的问题:
为什么调试代码 Debug.WriteLine(&#34;在Second_binded&#34;中); 在ClockControl中的Second_binded依赖属性的setter中,从不调用&#39 ;二&#39;在模型ClockTime正在更新。
调用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?
非常欢迎任何能够启发我对C#的了解的想法和评论。
感谢
肯
答案 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();
强制它,这不是使用绑定的正确方法。