绑定到UserControl的DependencyProperty

时间:2011-12-20 08:51:01

标签: wpf binding user-controls dependency-properties

我创建一个类似于输入时间的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的缩写形式。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我已经更新了你的代码,你不需要激活属性更改事件的依赖属性。

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

希望这会有所帮助