关于用户控件中DependencyProperty的setter中代码的问题
Questions about codes in the setter of a DependencyProperty in a user control
我正在页面上显示 time/clock 作为用户控件 (ClockControl
),实际时间模型由另一个 [=96] 的 DateTime
对象驱动=] (ClockTime
)。我在 ClockControl
:
上有 2 个文本块
Textblock 'Second_update_by_binding' 绑定到依赖项 属性 'Second_binded',后者又绑定到模型 ClockTime 'Second'.
Textblock 'Second_update_by_manipulating' 通过操纵模型 ClockTime 'Second' 的值进行更新,以便在 'Second' 仅为 1 时在前面添加“0”数字(或小于 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();
}
}
时钟时间模型:
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("in Second_binded");在setter的[=更新模型 ClockTime 中的 'Second' 时,永远不会调用 ClockControl 中的 90=] 依赖项 属性。
代码Debug.WriteLine("in Second_manipulated");内setter of Second_manipulated 调用 ClockControl 中的依赖项 属性 并且代码 Value_1.Text = (Convert.ToInt32(value)<10) ? "0"+value : value; 被执行以更改 ClockControl 上的文本,但它仅在添加另一个 DispatchTimer withtin MainPage.cs 以强制代码 [=87 后才起作用=] = clock.Second.ToString(); 更新时间。为什么我必须以这种方式更新 Second_manipulated,即使我已经在 MainPage.xaml?
中将 Second_manipulated 绑定到 Second
非常欢迎任何启发我的 C# 知识的想法和评论。
谢谢
肯
如果您想跟踪 DependencyProperty
中的更改,您必须注册一个 PropertyChangedCallback 处理程序。 属性 setter 绑定值更新时系统不会触发。
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();
强行命中,这不是绑定的正确使用方式
我正在页面上显示 time/clock 作为用户控件 (ClockControl
),实际时间模型由另一个 [=96] 的 DateTime
对象驱动=] (ClockTime
)。我在 ClockControl
:
Textblock 'Second_update_by_binding' 绑定到依赖项 属性 'Second_binded',后者又绑定到模型 ClockTime 'Second'.
Textblock 'Second_update_by_manipulating' 通过操纵模型 ClockTime 'Second' 的值进行更新,以便在 'Second' 仅为 1 时在前面添加“0”数字(或小于 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();
}
}
时钟时间模型:
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("in Second_binded");在setter的[=更新模型 ClockTime 中的 'Second' 时,永远不会调用 ClockControl 中的 90=] 依赖项 属性。
代码Debug.WriteLine("in Second_manipulated");内setter of Second_manipulated 调用 ClockControl 中的依赖项 属性 并且代码 Value_1.Text = (Convert.ToInt32(value)<10) ? "0"+value : value; 被执行以更改 ClockControl 上的文本,但它仅在添加另一个 DispatchTimer withtin MainPage.cs 以强制代码 [=87 后才起作用=] = clock.Second.ToString(); 更新时间。为什么我必须以这种方式更新 Second_manipulated,即使我已经在 MainPage.xaml?
中将 Second_manipulated 绑定到 Second
非常欢迎任何启发我的 C# 知识的想法和评论。
谢谢
肯
如果您想跟踪 DependencyProperty
中的更改,您必须注册一个 PropertyChangedCallback 处理程序。 属性 setter 绑定值更新时系统不会触发。
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();
强行命中,这不是绑定的正确使用方式