2011-05-11 14 views
0

複数のGridViewColumnを含むListViewがあります。いくつかの列はチェックボックスです。各列ヘッダーは、その列のすべてのチェックボックスをオンまたはオフにするという目的で、チェックボックスで構成されています。各行のチェックボックスは、ビューモデルのプロパティにバインドされています。私はシナリオがチェックボックスの単一の列であるいくつかの投稿を見てきましたが、私はチェックボックスの4列を持っているので、それらのソリューションのどれも私のために働くことはありません。 1回の訪問から次の訪問まで選択の状態を維持する必要もあります(すべて、列内のチェックボックスの一部またはすべてをチェックできます)。複数のチェックボックス列があり、すべての列ヘッダーが選択されたWPF GridView

<ListView ItemsSource="{Binding AveragingParameters}"> 
    <ListView.View> 
    <GridView AllowsColumnReorder="False"> 

     <GridViewColumn Header="Parameter"> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <DockPanel> 
       <TextBlock Text="{Binding Name}" /> 
      </DockPanel> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 
     </GridViewColumn> 

     <GridViewColumn> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <Grid HorizontalAlignment="Stretch"> 
       <CheckBox x:Name="chkAvg" IsChecked="{Binding CalcAverage}" /> 
      </Grid> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 
     <Grid> 
      <CheckBox x:Name="chkAvgSelectAll" Content="Avg" ToolTip="Select All" /> 
     </Grid> 
     </GridViewColumn> 

     <GridViewColumn> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <Grid HorizontalAlignment="Stretch"> 
       <CheckBox x:Name="chkMin" IsChecked="{Binding CalMin}" /> 
      </Grid> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 
     <Grid> 
      <CheckBox x:Name="chkMinSelectAll" Content="Min" ToolTip="Select All" /> 
     </Grid> 
     </GridViewColumn> 

    </GridView> 
    </ListView.View> 
</ListView> 

私は、コマンドとコマンドパラメータを使用してみましたCheckedプロパティのイベントをにPropertyChanged、そして背後にある私のコードでチェックイベントを処理しました:ここ

は私のListViewのためのXAMLの簡略版ですしかし、私が縛られているコレクションで何を変えるべきかを知るための十分な情報は得られません。

それぞれ別々のイベントハンドラを作成することができますが、可能であれば、単一のイベントハンドラでこれを処理できるようにしたいと思います。最終的には、もっと複雑なカスタムコントロールを作成するためです表示される列の点で事前

+0

ユーザが 'chkAvgSelectAll'または' chkMinSelectAll'をチェックまたはチェック解除するときに、 'AveragingParameters'でどのような変更が必要かを知りたいですか? –

+0

私はビューモデルにリンクする方法を理解し、AveragingParametersコレクション内の各アイテムにどのブール値プロパティを適用する必要があるかを判断しようとしています。 H.B.のポストは、チケットであるかもしれません。 – KyleLib

+0

私はこの問題を理解しているかどうかはわかりません。 ModelView内の個々のプロパティ/フィールドに各列をバインドすると、そのチェックボックスの状態が変更されると、基になるバインドされたオブジェクトも変更されます。バインディングを介してどのブール値のプロパティを明示的に決定する必要はありません。たぶん私はその質問を理解していないかもしれません。 – SRM

答えて

1

のいずれかを変更することができ、私は設定したいとTagおよびCheckboxのIsSelectedプロパティにバインドされたマルチバインディングに設定されたCommandParameter。コードは次のとおりです。

マイビューのXAMLリソース:

<UserControl.Resources> 
    <converters:NameValueMultiBindingConverter x:Key="SelectAllConverter" /> 
</UserControl.Resources> 

マイビューのXAMLを:

<ListView ItemsSource="{Binding AveragingParameters}"> 
    <ListView.View> 
    <GridView AllowsColumnReorder="False"> 

     <GridViewColumn Header="Parameter"> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <DockPanel> 
       <TextBlock Text="{Binding Name}" /> 
      </DockPanel> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 
     </GridViewColumn> 

     <GridViewColumn> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <Grid HorizontalAlignment="Stretch"> 
       <CheckBox x:Name="chkAvg" IsChecked="{Binding CalcAverage}" /> 
      </Grid> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 

     <CheckBox x:Name="chkAvgSelectAll" Content="Avg" 
        Tag="CalcAvg" Command="SelectAllCheckedCommand" 
        ToolTip="Select All"> 
      <MultiBinding Converter="{StaticResource SelectAllConverter}"> 
       <Binding Path="Tag" RelativeSource="{RelativeSource self}" /> 
       <Binding Path="IsChecked" RelativeSource="{RelativeSource self}" /> 
      </MultiBinding> 
     </CheckBox> 
     </GridViewColumn> 

     <GridViewColumn> 
     <GridViewColumn.CellTemplate> 
      <DataTemplate> 
      <Grid HorizontalAlignment="Stretch"> 
       <CheckBox x:Name="chkMin" IsChecked="{Binding CalMin}" /> 
      </Grid> 
      </DataTemplate> 
     </GridViewColumn.CellTemplate> 

     <CheckBox x:Name="chkMinSelectAll" Content="Avg" 
        Tag="CalcMin" Command="SelectAllCheckedCommand" 
        ToolTip="Select All"> 
      <MultiBinding Converter="{StaticResource SelectAllConverter}"> 
       <Binding Path="Tag" RelativeSource="{RelativeSource self}" /> 
       <Binding Path="IsChecked" RelativeSource="{RelativeSource self}" /> 
      </MultiBinding> 
     </CheckBox> 
     </GridViewColumn> 

    </GridView> 
    </ListView.View> 
</ListView> 

マイMultiValueConverter:

public class NameValueMultiBindingConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, 
          System.Globalization.CultureInfo culture) 
    { 

     var parameters = (object[])values; 
     return new NameValueConverterResult 
         { 
          Name = (string)parameters[0], 
          Value = parameters[1] 
         }; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, 
           System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

私が使用している結果オブジェクトコンバータ:

public class NameValueConverterResult 
{ 
    //The name of the model property to set 
    public string Name { get; set; } 

    //The value we're setting it to 
    public object Value { get; set; } 
} 

DelegateCommand(私はPRISMを使用しています)とハンドラ私のビューモデルで

public ICommand SelectAllCheckedCommand { get; private set; } 
private void OnSelectAllCheckedCommand(object arg) 
{ 
    if (arg == null || !(arg is NameValueConverterResult)) return; 

    NameValueConverterResult prop = arg as NameValueConverterResult; 

    //Reflect on the model to find the property we want to update. 
    PropertyInfo propInfo = Averagers.FirstOrDefault().GetType().GetProperty(prop.Name); 
    if (propInfo == null) return; 

    //Set the property on the Model 
    foreach (var item in Averagers) 
     propInfo.SetValue(item, prop.Value, null); 
} 

私は私が思いついた解決策を提供するのStackOverflowを悪用ないよ願っています。私はここでのエチケットについて確信が持てませんでした。

+0

虐待は受け付けていません...;) –

0

おかげでジャスト例えば、必要に応じて多くの情報として引き渡すと反射を経て、残りを行います

<ListView ItemsSource="{Binding DpData}"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn> 
       <GridViewColumn.CellTemplate> 
        <DataTemplate> 
         <CheckBox IsChecked="{Binding IsActive}"/> 
        </DataTemplate> 
       </GridViewColumn.CellTemplate> 
       <!-- Pass collection to Tag property, relevant member info is in the Content, 
        could also create an array in the Tag if the Content should be a nicer 
        looking string. --> 
       <CheckBox Content="IsActive" Click="CheckBox_Click" Tag="{Binding DpData}"/> 
      </GridViewColumn> 
     </GridView> 
    </ListView.View> 
</ListView> 
// This method could be used for all columns, 
// as long as they contain the necessary info 
// which should be provided in the XAML: 
//  - Item Collection 
//  - Property Name 
private void CheckBox_Click(object sender, RoutedEventArgs e) 
{ 
    var cb = sender as CheckBox; 
    var items = cb.Tag as IEnumerable; 
    PropertyInfo prop = null; 
    foreach (var item in items) 
    { 
     if (prop == null) 
     { 
      var type = item.GetType(); 
      var propname = cb.Content as string; 
      prop = type.GetProperty(propname); 
     } 
     prop.SetValue(item, cb.IsChecked, null); 
    } 
} 
+0

ポストに感謝します。私はそれを試してみましょう。私はDPDataが元の投稿で呼び出されたAveragedParametersと同義であると仮定しています。 – KyleLib

+0

どんな種類のItemsSourceでも、はい。 –

+0

あなたの投稿は私にいくつかのアイデアをくれました。私はMVVMを使用しているので、私の最終的なソリューションはMultiBindingを使用していました。私はすぐに私のソリューションを掲載します。 – KyleLib

0

あなたはMVVMのアプローチに固執したい場合はMVVMは、分離コードファイルに書き込むコードを避けるように私はバインディングのアプローチではなく、アプローチをイベント処理のために行くことをお勧め。

ビューモデルで2つのboolプロパティを単純にバインドする方法があります。IsChecked両方のチェックボックスのプロパティ。 INotifyPropetyChangedを使用して変更通知に基づいて、あなたはのItemsSourceすなわちAveragingParametersを反復処理し、私はモデルのプロパティの名前を含むタグと一緒にコマンドを使用して、私の問題を解決してきましたCalMinまたはCalcAverage

+2

これはMVVMのよくある誤解です。 MVVMはコードの背後に何も指示しません。それはあなたのコードの背後にビジネスロジックがないことを指示します。私はそれをこのように置いたと聞いた: "CodeBehindはデザイナーのドメインだけでなければならない"。言い換えれば、コードが後ろにある場合は、ビュー固有でビジネスロジックがないことを確認してください。そうしないと、ViewModelにビュー論理の混乱を招くことになります。ビューにビジネスロジックを置くことと同じくらい悪いことです。 – SRM

+0

投稿ありがとうbtw。私は実際にマルチバインディングを使ってこの問題を解決しました。私はすぐにそれを解決策として含める予定です。 – KyleLib

+0

@SRMはMVVMとコードビハインドに関して正しいと私は信じています。これらのガイドラインに従うことで、WPFやSilverlightのサポートが必要な場合は、他のビューを簡単にサポートできます。あなたの提案されたソリューションに関しては、私ができるならば、私は複数のプロパティへのバインディングを避けたいと思っていました。理由は、このコードの次の反復は、列の数を動的にする機能を可能にするユーザーコントロールになりそうです。今日私は4列のチェックボックスを持っています。将来の消費者は、異なるビューモデルを必要とし、多かれ少なかれ列を必要とするかもしれない。 – KyleLib

関連する問題