绑定到 UserControl 的 DependencyProperty

发布于 2024-12-22 13:31:29 字数 3115 浏览 4 评论 0原文

我创建一个 TimeInput 控件来输入时间。

<TextBox Text="{Binding Path=Hours}" />
<TextBox IsReadOnly="True"
         Focusable="False"
         Text=":" />
<TextBox Text="{Binding Path=Minutes}" />

public int Hours {
  get { return (int)this.GetValue(HoursProperty); }
  set {
    this.SetValue(HoursProperty, value);
    this.OnPropertyChanged("Hours");
  }
}

public static readonly DependencyProperty HoursProperty =
  DependencyProperty.Register("Hours", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));

private static void OnHoursChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    int newValue = (int)e.NewValue;
  }
}

public int Minutes {
  get { return (int)this.GetValue(MinutesProperty); }
  set {
    this.SetValue(MinutesProperty, value);
    this.OnPropertyChanged("Minutes");
  }
}

// Using a DependencyProperty as the backing store for Minutes.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinutesProperty =
  DependencyProperty.Register("Minutes", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));

private static void OnMinutesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    int newValue = (int)e.NewValue;
  }
}

public Nullable<TimeSpan> Value {
  get { return (Nullable<TimeSpan>)this.GetValue(ValueProperty); }
  set {
    this.SetValue(ValueProperty, value);
    this.OnPropertyChanged("Value");
  }
}

// Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value", typeof(Nullable<TimeSpan>), typeof(UserControl1), new UIPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged)));

private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    (obj as UserControl1).UpdateTime(e.NewValue as TimeSpan?);
  }
}

public void UpdateTime(TimeSpan? newTimeSpan) {
  if (newTimeSpan.HasValue) {
    this.Hours = newTimeSpan.Value.Hours;
    this.Minutes = newTimeSpan.Value.Minutes;
  }
}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string name) {
  PropertyChangedEventHandler handler = this.PropertyChanged;
  if (handler != null) {
    handler(this, new PropertyChangedEventArgs(name));
  }
}

#endregion

我在另一个 UserControl 上使用它并绑定到属性时,它不起作用并且显示值。 我这样使用它:

<uc:UserControl1 Value="{Binding StartTime}"/>

Item

public TimeSpan StartTime
{
  get { return new Types.Time(Item.StartTime).ToTimeSpan(); }
  set { Item.StartTime = new Types.Time(value).ToShort(); NotifyPropertyChanged("StartTime"); }
}

从数据库读取并绑定的实体,而 StartTime 是 hhmm 的缩写形式。

I Create a TimeInput Control Like to Enter Time.

<TextBox Text="{Binding Path=Hours}" />
<TextBox IsReadOnly="True"
         Focusable="False"
         Text=":" />
<TextBox Text="{Binding Path=Minutes}" />

and

public int Hours {
  get { return (int)this.GetValue(HoursProperty); }
  set {
    this.SetValue(HoursProperty, value);
    this.OnPropertyChanged("Hours");
  }
}

public static readonly DependencyProperty HoursProperty =
  DependencyProperty.Register("Hours", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));

private static void OnHoursChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    int newValue = (int)e.NewValue;
  }
}

public int Minutes {
  get { return (int)this.GetValue(MinutesProperty); }
  set {
    this.SetValue(MinutesProperty, value);
    this.OnPropertyChanged("Minutes");
  }
}

// Using a DependencyProperty as the backing store for Minutes.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinutesProperty =
  DependencyProperty.Register("Minutes", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));

private static void OnMinutesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    int newValue = (int)e.NewValue;
  }
}

public Nullable<TimeSpan> Value {
  get { return (Nullable<TimeSpan>)this.GetValue(ValueProperty); }
  set {
    this.SetValue(ValueProperty, value);
    this.OnPropertyChanged("Value");
  }
}

// Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value", typeof(Nullable<TimeSpan>), typeof(UserControl1), new UIPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged)));

private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
  if (obj != null) {
    (obj as UserControl1).UpdateTime(e.NewValue as TimeSpan?);
  }
}

public void UpdateTime(TimeSpan? newTimeSpan) {
  if (newTimeSpan.HasValue) {
    this.Hours = newTimeSpan.Value.Hours;
    this.Minutes = newTimeSpan.Value.Minutes;
  }
}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string name) {
  PropertyChangedEventHandler handler = this.PropertyChanged;
  if (handler != null) {
    handler(this, new PropertyChangedEventArgs(name));
  }
}

#endregion

While I use this on another UserControl and Bind to a Property It doesn't work and show values.
I use it like this:

<uc:UserControl1 Value="{Binding StartTime}"/>

and

public TimeSpan StartTime
{
  get { return new Types.Time(Item.StartTime).ToTimeSpan(); }
  set { Item.StartTime = new Types.Time(value).ToShort(); NotifyPropertyChanged("StartTime"); }
}

That Item is an entity read from database and bind and StartTime is short form of hhmm.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

日久见人心 2024-12-29 13:31:29

我已经更新了您的代码,使用依赖属性,您不需要显式地触发属性更改事件。

public partial class UserControl1 : UserControl
{
  public UserControl1() {
    this.InitializeComponent();
  }

  public int Hours {
    get { return (int)this.GetValue(HoursProperty); }
    set { this.SetValue(HoursProperty, value); }
  }

  public static readonly DependencyProperty HoursProperty =
    DependencyProperty.Register("Hours", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));

  private static void OnHoursChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      int newValue = (int)e.NewValue;
      uc.TimeValue = new TimeSpan(newValue, uc.Minutes, 0);
    }
  }

  public int Minutes {
    get { return (int)this.GetValue(MinutesProperty); }
    set { this.SetValue(MinutesProperty, value); }
  }

  // Using a DependencyProperty as the backing store for Minutes.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty MinutesProperty =
    DependencyProperty.Register("Minutes", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));

  private static void OnMinutesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      int newValue = (int)e.NewValue;
      uc.TimeValue = new TimeSpan(uc.Hours, newValue, 0);
    }
  }

  public Nullable<TimeSpan> TimeValue {
    get { return (Nullable<TimeSpan>)this.GetValue(ValueProperty); }
    set { this.SetValue(ValueProperty, value); }
  }

  public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("TimeValue", typeof(Nullable<TimeSpan>), typeof(UserControl1), new UIPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged)));

  private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      uc.UpdateTime(e.NewValue as TimeSpan?);
    }
  }

  public void UpdateTime(TimeSpan? newTimeSpan) {
    if (newTimeSpan.HasValue) {
      this.Hours = newTimeSpan.Value.Hours;
      this.Minutes = newTimeSpan.Value.Minutes;
    }
  }
}

其次,我认为您使用 StartTime 属性不正确,也将其用作依赖属性,或实现 INotifyPropertyChanged。

{
  // .....
  StartTime = new Types.Time(this.Item.StartTime).ToTimeSpan();
  // .....
}


public static readonly DependencyProperty StartTimeProperty =
  DependencyProperty.Register("StartTime", typeof(TimeSpan?), typeof(Window1), new PropertyMetadata(default(TimeSpan?), new PropertyChangedCallback(OnStartTimePropertyChanged)));

private static void OnStartTimePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
  if(e.NewValue != e.OldValue) {
    (dependencyObject as Window1).Item.StartTime = new Types.Time(e.NewValue).ToShort();
  }
}

public TimeSpan? StartTime {
  get { return (TimeSpan?)GetValue(StartTimeProperty); }
  set { SetValue(StartTimeProperty, value); }
}

希望这有帮助

i have updated your code, with dependency properties you don't need fire the property changed event explicit.

public partial class UserControl1 : UserControl
{
  public UserControl1() {
    this.InitializeComponent();
  }

  public int Hours {
    get { return (int)this.GetValue(HoursProperty); }
    set { this.SetValue(HoursProperty, value); }
  }

  public static readonly DependencyProperty HoursProperty =
    DependencyProperty.Register("Hours", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));

  private static void OnHoursChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      int newValue = (int)e.NewValue;
      uc.TimeValue = new TimeSpan(newValue, uc.Minutes, 0);
    }
  }

  public int Minutes {
    get { return (int)this.GetValue(MinutesProperty); }
    set { this.SetValue(MinutesProperty, value); }
  }

  // Using a DependencyProperty as the backing store for Minutes.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty MinutesProperty =
    DependencyProperty.Register("Minutes", typeof(int), typeof(UserControl1), new UIPropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));

  private static void OnMinutesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      int newValue = (int)e.NewValue;
      uc.TimeValue = new TimeSpan(uc.Hours, newValue, 0);
    }
  }

  public Nullable<TimeSpan> TimeValue {
    get { return (Nullable<TimeSpan>)this.GetValue(ValueProperty); }
    set { this.SetValue(ValueProperty, value); }
  }

  public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("TimeValue", typeof(Nullable<TimeSpan>), typeof(UserControl1), new UIPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged)));

  private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
    var uc = obj as UserControl1;
    if (uc != null && e.NewValue != e.OldValue) {
      uc.UpdateTime(e.NewValue as TimeSpan?);
    }
  }

  public void UpdateTime(TimeSpan? newTimeSpan) {
    if (newTimeSpan.HasValue) {
      this.Hours = newTimeSpan.Value.Hours;
      this.Minutes = newTimeSpan.Value.Minutes;
    }
  }
}

second, i think you use the StartTime property incorrect, use it as dependency property too, or implement INotifyPropertyChanged.

{
  // .....
  StartTime = new Types.Time(this.Item.StartTime).ToTimeSpan();
  // .....
}


public static readonly DependencyProperty StartTimeProperty =
  DependencyProperty.Register("StartTime", typeof(TimeSpan?), typeof(Window1), new PropertyMetadata(default(TimeSpan?), new PropertyChangedCallback(OnStartTimePropertyChanged)));

private static void OnStartTimePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
  if(e.NewValue != e.OldValue) {
    (dependencyObject as Window1).Item.StartTime = new Types.Time(e.NewValue).ToShort();
  }
}

public TimeSpan? StartTime {
  get { return (TimeSpan?)GetValue(StartTimeProperty); }
  set { SetValue(StartTimeProperty, value); }
}

hope this helps

习ぎ惯性依靠 2024-12-29 13:31:29

您不应该有任何其他代码,然后在依赖属性的 getter 和 setter 中调用 GetValue 和 SetValue。但这可能无法解决您的问题。如果您想在值更改时调用一些代码,请在回调方法而不是 setter 中执行此操作。

You should not have any other code then calling GetValue and SetValue inside getter and setter of dependency property. But this may not resolve you problem. If you want to call some code when value change then do that inside callback method instead of setter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文