【问题标题】:Binding to DependencyProperty of a UserControl绑定到 UserControl 的 DependencyProperty
【发布时间】:2011-12-20 08:51:01
【问题描述】:

我创建一个 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}"/>

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

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

【问题讨论】:

  • 你不需要 INotifyPropertyChanged,因为 DP 系统已经完成了,只需要依赖它。

标签: wpf binding user-controls dependency-properties


【解决方案1】:

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

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

希望对你有帮助

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 通常情况下,withing 的代码会被忽略,并且与执行流程无关。
    猜你喜欢
    • 2012-06-06
    • 2013-06-03
    • 1970-01-01
    • 2013-01-20
    • 2014-06-22
    • 2016-05-13
    • 2014-12-22
    • 1970-01-01
    相关资源
    最近更新 更多