WPF GridView с несколькими столбцами флажков и выбором заголовка всех столбцов - PullRequest
0 голосов
/ 11 мая 2011

У меня есть ListView, содержащий несколько GridViewColumns.Некоторые из столбцов являются флажками.Заголовок каждого столбца также состоит из флажка, с целью установить / снять все флажки в этом столбце.Флажки каждой строки связаны со свойствами в моей модели представления.Я видел несколько публикаций, где сценарий представляет собой один столбец флажков, но ни одно из этих решений не будет работать для меня, поскольку у меня есть 4 столбца флажков.Мне также нужно сохранить состояние выборов от одного посещения до следующего (все, некоторые или некоторые из флажков в столбце могут быть проверены).

Вот сокращенная версия XAML для моего ListView:

<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>

Я пытался использовать команды и параметры команд, события PropertyChanged для свойства Checked и обрабатывать событие Checked в своем коде, но ничего не дает мне достаточно информации, чтобы знать, что изменить в коллекцииЯ обязан.

Полагаю, я мог бы создать отдельный обработчик событий для каждого, но я хотел бы иметь возможность обрабатывать это в отдельном обработчике событий, если это возможно, потому что в конечном итоге я буду создаватьпользовательский элемент управления, который немного более податлив с точки зрения отображаемых столбцов.

Заранее спасибо

Ответы [ 3 ]

1 голос
/ 12 мая 2011

Я решил свою проблему, используя команду вместе с тегом, содержащим имя свойства модели, которое я хочу установить, и параметром CommandParameter, установленным для множественного связывания, который связан с тегом и свойством IsSelected флажка.Код выглядит следующим образом:

Xaml ресурсы My View:

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

Xaml My View:

<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>

My 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 голосов
/ 11 мая 2011

Если вы хотите придерживаться подхода MVVM, я бы предложил использовать подход связывания, а не подход обработки событий, поскольку MVVM избегает написания кода в коде файла.

Одним из способов может быть просто связать два свойства bool в модели представления с помощью IsChecked Свойство обоих флажков. Основываясь на уведомлении об изменении с помощью INotifyPropetyChanged, вы можете перебирать свой источник элементов, т.е. AveragingParameters, и изменять либо CalMin, либо CalcAverage

0 голосов
/ 11 мая 2011

Просто передайте столько информации, сколько необходимо, и сделайте все остальное с помощью размышления, например,

<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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...