2012-01-10 33 views
1

首先,爲所有的XAML道歉。我已經嘗試了幾天來解決這個問題,但我一定會錯過一些東西。總結的問題是我的UserControl依賴項屬性在使用代碼隱藏時不會出現在數據綁定中。數據綁定在一個簡單的UserControl中失敗

詳細信息:我有以下簡單UserControl(在其自己的DLL),在那裏我使用滑塊從0..59選擇秒,UserControl有一個返回組成的一個TimeSpan依賴項屬性Value經由滑塊選擇秒:

public partial class TinyTimeSpanControl : UserControl, INotifyPropertyChanged 
{ 
    public TinyTimeSpanControl() 
    { 
     InitializeComponent(); 
    } 

    private int _seconds; 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    public int Seconds 
    { 
     get { return _seconds; } 
     set 
     { 
      if (_seconds == value) 
       return; 
      _seconds = value; 
      RaisePropertyChanged("Seconds"); 

      var t = Value; 
      Value = new TimeSpan(t.Hours, t.Minutes, _seconds); 
     } 
    } 

    public TimeSpan Value 
    { 
     get { return (TimeSpan) GetValue(ValueProperty); } 
     set { SetValue(ValueProperty, value); } 
    } 

    private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     TinyTimeSpanControl control = obj as TinyTimeSpanControl; 
     var newValue = (TimeSpan)e.NewValue; 

     control.Seconds = newValue.Seconds; 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
     "Value", typeof(TimeSpan), typeof(TinyTimeSpanControl), new PropertyMetadata(OnValueChanged)); 
} 

使用簡單(消隱)XAML:

<UserControl x:Class="WpfControlLibrary1.TinyTimeSpanControl" x:Name="root"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 
    <Slider Name="SecondsSlider" 
      Width="120" 
      Height="23" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      LargeChange="5" 
      SelectionStart="0" 
      SmallChange="1" 
      Value="{Binding Path=Seconds, 
          ElementName=root}" SelectionEnd="59" Maximum="59" /> 
    <Label Name="label1" 
      Grid.Column="1" 
      Content="{Binding ElementName=SecondsSlider, 
          Path=Value}" /> 
    <Label Name="label2" 
      Grid.Column="2" 
      Content="Seconds" /> 
</Grid> 
</UserControl> 

在控制的結合工作正常。現在

當我編譯此,再加入TinyTimeSpanControl到我的窗戶一(消隱):

<Window x:Class="WpfControls.MainWindow" 
      xmlns:my="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1" 
      x:Name="root" 
      Closing="root_Closing"> 
     <Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto" /> 
       <RowDefinition Height="Auto" /> 
       <RowDefinition Height="142*" /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto" /> 
       <ColumnDefinition Width="Auto" /> 
       <ColumnDefinition Width="Auto" /> 
      </Grid.ColumnDefinitions> 
      <my:TinyTimeSpanControl Name="tinyTimeSpanControl1" 
            HorizontalAlignment="Left" 
            VerticalAlignment="Top" 
            Value="{Binding ElementName=root, 
                Path=TheTime}" /> 
      <Label Name="label1" 
        Grid.Column="1" 
        Content="{Binding ElementName=tinyTimeSpanControl1, 
            Path=Value}" /> 
      <Label Name="label2" 
        Grid.Column="2" 
        Content="{Binding ElementName=root, 
            Path=TheTime}" /> 

     </Grid> 
    </Window> 

在我的主窗口:

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    private TimeSpan _theTime = new TimeSpan(0, 0, 33); 
    public TimeSpan TheTime 
    { 
     get 
     { 
      return _theTime; 
     } 
     set 
     { 
      if (_theTime == value) 
       return; 

      _theTime = value; 
      RaisePropertyChanged("TheTime"); 
     } 
    } 

數據綁定部分作品:

  • tinyTimeSpanControl1最初設置爲TheTime屬性的值我的代碼隱藏在我的主窗口後面
  • tinyTimeSpanControl1更新label1當滑塊移動時。

但不工作:

  • 當滑塊移動,label2仍然設置爲TheTime

原始版本把一個斷點在Window_closing事件表明,TheTime還沒有改變。

我錯過了一些需要在我的UserControl中提出的事件嗎?

謝謝,並再次對所有的xaml(這是最小的情況)再次道歉。

+1

你的代碼是真的* *困惑,首先,標籤不是簡單的文字顯示,但標註的輸入控制(他們有訪問文本支持並使用'Target'屬性引用輸入元素),而是使用'TextBlocks'。其次,如果你只想在綁定文本旁邊顯示靜態文本,你可以使用'Binding.StringFormat'來添加它。 – 2012-01-10 12:29:47

+0

我使用INPC來避免使用硬編碼事件,這就是爲什麼它看起來可能比預期更復雜一些。 – Barry 2012-01-10 14:05:58

回答

2

這就是問題所在:

Value = new TimeSpan(t.Hours, t.Minutes, _seconds); 

這將清除出你在窗口設立,只是設置一個值綁定。在UserControl代碼中,您不應使用SetValue,而是使用SetCurrentValue,該屬性保持屬性上的綁定不變。

一些其他的事情可能會關閉,以及我沒有看到尚未...

+0

謝謝。這是問題的一半。我剛剛發現的完整解決方案是在我的主窗口中添加:'Mode = TwoWay'到'TinyTimeSpanControl'綁定。當你的回答幫助我指出正確的方向時,就會發生碰撞。 – Barry 2012-01-10 14:04:39

+0

或更新的代碼背後:'公共靜態只讀的DependencyProperty ValueProperty = DependencyProperty.Register( 「價值」 的typeof(時間跨度)的typeof(TinyTimeSpanControl),新FrameworkPropertyMetadata(TimeSpan.Zero,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,OnValueChanged));' – Barry 2012-01-10 14:13:34

+1

@Barry:哦,是的,默認綁定模式確實是錯誤的另一個重要來源。 – 2012-01-10 15:35:34