2013-04-01 2 views
7

私はXAMLの新機能ですが、学習するのが楽しいです。私が本当に苦労しているのは、要素にプロパティをバインドすることです。DataTemplateです。XAML:DataTemplateのプロパティをバインドする

単純なWPFの例を作成しましたが、うまくいけば私の問題を説明できます。

私はVisibilityCheckBoxのプロパティをにバインドしようとしていますが、私のviewmodelのプロパティにバインドしようとしています。

私はItemという単純なデータモデルを持っていますが、この例ではほとんど関係ありません。

class Item : INotifyPropertyChanged 
{ 

    // Fields... 
    private bool _IsRequired; 
    private string _ItemName; 

そして、非常に単純なViewViewという名前のモデルViewViewModel。

class ItemViewModel : INotifyPropertyChanged 
{ 
    private ObservableCollection<Item> _Items; 
    private bool _IsCheckBoxChecked; 
    private bool _IsCheckBoxVisible; 

    public ObservableCollection<Item> Items 
    { 
     get { return _Items; } 
     set { _Items = value; } 
    } 


    public bool IsCheckBoxChecked 
    { 
     get { return _IsCheckBoxChecked; } 
     set 
     { 
      if (_IsCheckBoxChecked == value) 
       return; 
      _IsCheckBoxChecked = value; 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxChecked")); 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible")); 
      } 
     } 
    } 


    public bool IsCheckBoxVisible 
    { 
     get { return !_IsCheckBoxChecked; } 
     set 
     { 
      if (_IsCheckBoxVisible == value) 
       return; 
      _IsCheckBoxVisible = value; 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible")); 
     } 

(コンストラクタとINotifyPropertyChanged実装を簡潔にするために省略。)次のようにMainPage.xamlをにレイアウト

コントロール。

<Window.Resources> 
    <local:VisibilityConverter x:Key="VisibilityConverter"/> 
</Window.Resources> 

<Window.DataContext> 
    <local:ItemViewModel/> 
</Window.DataContext> 

<Grid> 
    <StackPanel> 
     <CheckBox x:Name="checkBox" Content="Hide CheckBoxes" FontSize="14" IsChecked="{Binding IsCheckBoxChecked, Mode=TwoWay}" /> 
     <ListView ItemsSource="{Binding Items}" HorizontalContentAlignment="Stretch" > 
      <ListView.ItemTemplate > 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock Text="{Binding ItemName}"/> 
         <CheckBox Grid.Column="1" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" > 
          <CheckBox.DataContext> 
           <local:ItemViewModel/> 
          </CheckBox.DataContext> 
         </CheckBox> 
        </Grid> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
     <StackPanel Orientation="Horizontal" Margin="4,4,0,0"> 
     <TextBlock Text="IsCheckBoxVisible:"/> 
      <TextBlock Text="{Binding IsCheckBoxVisible}" Margin="4,0,0,0" FontWeight="Bold" /> 
     </StackPanel > 
     <Button Content="Button" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" Margin="4,4,4,4"/> 
    </StackPanel> 

</Grid> 

「隠すチェックボックス」のチェックボックスをIsCheckBoxCheckedにバインドされているとIsCheckBoxVisibleを更新するために使用されます。私はまた、DataTemplateの下にいくつかの追加のコントロールを追加して、(自分自身に)すべてが機能することを証明しました)。

私はJeff Wilcoxのバリューコンバータも実装しました。 、私は「隠すチェックボックス」をチェックし、チェックをはずす、アプリを実行すると、予想通り、DataTemplate関数の外部制御http://www.jeff.wilcox.name/2008/07/visibility-type-converter/

を(ありがとう)悲しいかな、データテンプレート内のCheckboxは変わりません。

私は成功を収めている:

IsVisible="{Binding IsChecked, Converter={StaticResource VisibilityConverter}, ElementName=checkBox}" 

しかし、私はちょうど別のコントロールを模倣するが値に基づいて決定を下すつもりはありませんよ。

あなたが提供できるヘルプやアドバイスは本当にありがたいです。

ありがとうございます。

+0

Visual Studioのデバッグ出力ウィンドウにバインディングエラーがありますか?彼らは通常何がうまくいかないのかを示す良い指標です。 – ChrisF

+0

Chris。ご回答いただきありがとうございます。アウトプットウィンドウをチェックし、疑わしい通りにエラーが発生しました。 IsCheckBoxVisibleが見つかりませんでした。以下のダンカンの返答のように修正を適用してください。ありがとうございました。 – Dowse

答えて

15

DataTemplateを使用している場合、DataContextはデータテンプレートオブジェクトです(この場合はItem)。したがって、DataTemplateのCheckBoxのDataContextはItemViewModelではなくItemです。あなたは<TextBlock Text="{Binding ItemName}"/>によってこれを見ることができ、これはItemクラスのプロパティにバインドします。 IsCheckBoxVisibleへのバインディングは、ItemにあるIsCheckBoxVisibleというプロパティを検索しようとしています。

は、この回避する方法がいくつかありますが、これまでで最も簡単にこれを行うことです:、それとのxを与える(XAMLで)あなたの窓に

を:名前。例:

<CheckBox Grid.Column="1" 
      Visibility="{Binding DataContext.IsCheckBoxVisible, ElementName=MyWindow, Converter={StaticResource VisibilityConverter}}"> 

私たちは、あなたのItemViewModelであるべきである(そのDataContextのプロパティを見て、バインディングのソースとしてウィンドウを使用している:

<Window [...blah blah...] 
     x:Name="MyWindow"> 
があなたのように見えるようにバインドを変更

あなたは手の込んだ何かをしたい場合は、その後IsCheckBoxVisibleプロパティを引き抜く。

別のオプションは、あなたのDataContextを参照するためにプロキシオブジェクトを使用することです。this article on DataContextProxyを参照してください。

+1

ダンカン。迅速な返信ありがとうございます。私はあなたの提案を試みました、そして、それは魅力のように機能しました。私はチェックボックスのための別のタグを追加すると思ったが、悲しいかな、いいえ。もう一度あなたに感謝します。あなたが提供したリンクでDan Wahlinのatricleに読書を与えます。 (私はあなたの答えを投票しようとしましたが、私の低い評判は私がそうするのを妨げています。) – Dowse

+0

喜んで私は助けることができました! :-)これは完全には関係ありませんが、あなたのコメントからは、要素のDataContext(ウィンドウや別のルートを除く)を手動で設定することは、非常に慎重にしたいことです。間違ったことをしている。あなたの試みが ''の行に沿っていると想像しています。もしそうなら、あなたが作成しているようにItemViewModelをxamlで定義するとき* 1つで、異なるインスタンスを持つことになります。あなたはこれを回避することができますが、私が説明した解決策が優れています。 –

関連する問題