2012-01-10 13 views
1

まず、すべてのXAMLについて申し訳ありません。私はこれを解決するために数日間試しましたが、私は何かが欠けているに違いありません。要約すると、私のUserControl依存関係プロパティは、コードビハインドが使用されているときにデータバインドに現れません。単純なUserControlでデータバインディングが失敗する

詳細:私は秒を選択することが0..59からスライダーを使用しています、とUserControlがで構成されるTimeSpanを返し依存関係プロパティValueを持って次のような単純なUserControl(独自のDLL内)を、持っていますスライダーを介して、選択秒:

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の値に設定されています。私のメインウィンドウの背後にあるコード
  • tinyTimeSpanControl1label1スライダを動かすと。

しかし、動作しません:

  • スライダーが移動し、label2が残っWindow_closingイベントの中でブレークポイントを置くTheTime

の元のバージョンに設定がTheTimeしていないことを示していますかわった。

私はUserControlに提起する必要があるいくつかのイベントがありませんか?

すべてのxamlについてもう一度お詫び申し上げます(これは最小のケースでもあります)。

+1

あなたのコードは*本当に*混乱、すべての最初で、ラベルは、(単純なテキスト表示のためではなく、入力コントロールにラベルを付けます彼らはアクセステキストサポートを持っていて、 'Target'プロパティを使ってinput要素を参照します)、代わりに' TextBlocks'を使います。次に、バインドされたテキストの横に静的なテキストを表示したい場合は、それを追加するために 'Binding.StringFormat'を使うことができます。 –

+0

私はハードコードされたイベントの使用を避けるためにINPCを使用しています。なぜなら、予想よりも少し複雑に見えるかもしれないからです。 – Barry

答えて

2

これが問題である:

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

これは、あなたの窓に設立され、単に値を設定バインディングをクリアします。 UserControlコードでは、SetValueではなく、SetCurrentValueを使用してプロパティのバインディングをそのまま維持してください。

いくつかの他のものが同様に私はまだ見ていないことをオフになる場合もあります...

+0

ありがとうございます。それは問題の半分です。私が今発見した完全な解決策は、メインウィンドウの 'TinyTimeSpanControl'バインディングに' Mode = TwoWay'を追加することです。あなたの答えが間違った方向に私を向けるのに役立ちました。 – Barry

+0

または更新コードの背後に: 'パブリック静的読み取り専用たDependencyProperty ValueProperty = DependencyProperty.Register( "値"、typeof演算(のTimeSpan)、typeof演算(TinyTimeSpanControl)、新しいFrameworkPropertyMetadata(TimeSpan.Zero、FrameworkPropertyMetadataOptions.BindsTwoWayByDefault、OnValueChanged));' – Barry

+1

@バリー:ああ、デフォルトのバインディングモードは実際にはエラーのもう一つの大きな原因です。 –

関連する問題