2013-05-09 54 views
7

我在自定義用戶控件上進行數據綁定時遇到了困難。我創建了一個示例項目來強調我的問題。我對WPF和MVVM完全陌生,所以忍受着我......在自定義用戶控件的DependencyProperty上進行綁定而不是在更改時更新

我創建了一個簡單的視圖,它使用數據綁定兩種方式。內置控制的數據綁定工作得很好。我的自定義控件不......我在我的控件的PropertyChangedCallback中放置了一個斷點。它在啓動時會被擊中一次,但不會再次。同時,我已經綁定到相同價值的標籤愉快地倒計時。

我錯過了什麼?我的例子項目如下:

主窗口:

<Window x:Class="WpfMVVMApp.MainWindow" 
     xmlns:local="clr-namespace:WpfMVVMApp" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.DataContext> 
      <local:CountdownViewModel /> 
     </Grid.DataContext> 
     <Label Name="custName" Content="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45" VerticalAlignment="Top"></Label> 
     <local:UserControl1 MinutesRemaining="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45"></local:UserControl1> 
    </Grid> 
</Window> 

這裏是我的模型:

namespace WpfMVVMApp 
{ 

    public class CountdownModel : INotifyPropertyChanged 
    { 
     private int chargeTimeRemaining_Mins; 
     public int ChargeTimeRemaining_Mins 
     { 
      get 
      { 
       return chargeTimeRemaining_Mins; 
      } 
      set 
      { 
       chargeTimeRemaining_Mins = value; 
       OnPropertyChanged("ChargeTimeRemaining_Mins"); 
      } 
     } 

     #region INotifyPropertyChanged Members 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
     #endregion 
    } 
} 

視圖模型:

namespace WpfMVVMApp 
{ 
    public class CountdownViewModel 
    { 
     public CountdownModel Countdown { get; set; } 

     DispatcherTimer timer; 
     private const int maxMins = 360; 

     public CountdownViewModel() 
     { 
      Countdown = new CountdownModel { ChargeTimeRemaining_Mins = 60 }; 

      // Setup timers 
      timer = new DispatcherTimer(); 
      timer.Tick += new EventHandler(this.SystemChargeTimerService); 
      timer.Interval = new TimeSpan(0, 0, 1); 
      timer.Start(); 
     } 

     private void SystemChargeTimerService(object sender, EventArgs e) 
     { 
      //convert to minutes remaining 
      // DEMO CODE - TODO: Remove 
      this.Countdown.ChargeTimeRemaining_Mins -= 1; 
     } 
    } 
} 

下面是我的用戶控制的XAML:

<UserControl x:Class="WpfMVVMApp.UserControl1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <Label Name="Readout"></Label> 
    </Grid> 
</UserControl> 

而這裏的用戶控件後面的代碼:

namespace WpfMVVMApp 
{ 
    public partial class UserControl1 : UserControl 
    { 
     #region Dependency Properties 
     public static readonly DependencyProperty MinutesRemainingProperty = 
        DependencyProperty.Register 
        (
         "MinutesRemaining", typeof(int), typeof(UserControl1), 
         new UIPropertyMetadata(10, new PropertyChangedCallback(minutesRemainChangedCallBack)) 
        ); 
     #endregion 

     public int MinutesRemaining 
     { 
      get 
      { 
       return (int)GetValue(MinutesRemainingProperty); 
      } 
      set 
      { 
       SetValue(MinutesRemainingProperty, value); 
      } 
     } 

     static void minutesRemainChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args) 
     { 
      UserControl1 _readout = (UserControl1)property; 
      _readout.MinutesRemaining = (int)args.NewValue; 

      _readout.Readout.Content = _readout.MinutesRemaining; 
     } 

     public UserControl1() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

回答

10

您更改回調更是打破了約束力。

作爲骨架:在你的窗口中你有UC.X="{Binding A}"然後在那個屬性改變(在UC)你有X=B;。這打破了約束,因爲在這兩種情況下,你設置了X

整改,刪除更改回調,這增加了標籤:

Content="{Binding MinutesRemaining, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" 
+0

謝謝你的答覆。綁定這是行得通的。但是,我創建依賴項屬性的原因是因爲我想在我的實際程序中設置更多的標籤(這只是一個簡單的例子)。 我現在看到我正在爲我的更改回調中的MinutesRemaining賦值,這會中斷原始綁定。我注意到這條線,現在它按我的預期工作。 – user2367999 2013-05-10 13:14:22

2

我想你的代碼工作正常,我做出的唯一改變是去掉後面的代碼propertychangedcallback你已經和數據綁定標籤(讀數)到依賴項屬性。

用戶控件(XAML)

<UserControl x:Class="WpfApplication1.UserControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <Label Name="Readout" Content="{Binding RelativeSource={RelativeSource 
          AncestorType=UserControl}, Path=MinutesRemaining}"/> 
    </Grid> 
</UserControl> 

用戶控件(代碼隱藏)

public partial class UserControl1 : UserControl 
{ 
    #region Dependency Properties 
    public static readonly DependencyProperty MinutesRemainingProperty = 
       DependencyProperty.Register 
       (
        "MinutesRemaining", typeof(int), typeof(UserControl1), 
        new UIPropertyMetadata(10) 
       ); 
    #endregion 

    public int MinutesRemaining 
    { 
     get 
     { 
      return (int)GetValue(MinutesRemainingProperty); 
     } 
     set 
     { 
      SetValue(MinutesRemainingProperty, value); 
     } 
    } 

    public UserControl1() 
    { 
     InitializeComponent(); 
    } 
} 
相關問題