Поменять элементы в сетке данных с помощью комбинированных столбцов? - PullRequest
1 голос
/ 13 апреля 2019

Что у меня есть

У меня есть UserControl, настроенный в шаблоне MVC с DataGrid и List моделями.В моем List больше элементов, чем может отобразить мой DataGrid, поэтому я искал способ создать способ, позволяющий моим пользователям самостоятельно выбирать элементы, которые они хотят видеть.

Что мне нужно

Мой DataGrid должен иметь возможность выполнять все следующие операции:

  • Отображать 8 из 30 элементов моего списка
  • Легко разрешать пользователямизменить элемент каждой строки
  • Обновлять модели в моем основном списке, когда пользователь изменяет значения ячеек в моей DataGrid (в случае, если я работаю со вторым списком, состоящим только из 8 элементов)

Как это должно выглядеть в идеале

Поскольку я пытаюсь создать собственный генератор таблиц символов для DSA игры Pen & Paper (черный глаз), я был бы рад сделать DataGrid идентичным их сетке.насколько возможно.

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

DSAPIC

Ранее я работал только с DevExpress GridControls, поэтому я изо всех сил пытаюсь получитьв DataGrids «по умолчанию», даже без реализации функциональности.

Дополнительная информация:

  • Я загружаю и сохраняю свои листы символов из / в XML-файлы
  • Таблицы символовдолжен быть напечатан

Вопрос

Как я могу заставить это работать так, как я себе это представлял / У вас есть другие / более простые решения для моей проблемы?

1 Ответ

1 голос
/ 20 апреля 2019

Две интересные вещи:

  1. Если вы хотите, чтобы обновления были видны во всех коллекциях, самый простой способ - убедиться, что все коллекции используют одни и те же ссылки для заполнения самих себя.
  2. Примечание: показ одной и той же записи более одного раза потребует особого внимания.Обновления могут показаться странными, так как они состоят из нескольких строк.LINQ-запросы могут возвращать другой экземпляр, чем предполагалось.В этом случае, однако, мы заинтересованы только в отображении уникальных записей с возможностью их замены.

Approach

Добавление свойства IsShown в модель представления вашей строки для отслеживания, видима ли запись в данный момент в сетке данных.Мы можем применить это, используя RowStyle.

Использование CollectionView для комбинированного списка, основанного на сетке данных ItemsSource.Если запись не отображается, ее следует выбрать из выпадающего списка.Добавление фильтра в представление коллекции должно помочь.

Пример кода

WeaponViewModel.cs

public class WeaponViewModel : ViewModelBase
{
    private readonly string _name;
    private string abbreviation;
    private int damage;
    private bool isShown;

    public WeaponViewModel(string name, string abbreviation, int damage, bool isShown)
    {
        _name = name;
        this.Abbreviation = abbreviation;
        this.Damage = damage;
        this.IsShown = isShown;
    }

    public string Name => _name;

    public string Abbreviation
    {
        get { return abbreviation; }
        set
        {
            abbreviation = value;
            OnPropertyChanged();
        }
    }

    public int Damage
    {
        get { return damage; }
        set
        {
            damage = value;
            OnPropertyChanged();
        }
    }

    public bool IsShown
    {
        get { return isShown; }
        set
        {
            isShown = value;
            OnPropertyChanged();
        }
    }
}

MainViewModel.cs

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        Weapons = new ObservableCollection<WeaponViewModel>(GetWeapons());
        DropDownWeapons = (CollectionView)new CollectionViewSource { Source = Weapons }.View;
        DropDownWeapons.Filter = DropDownFilter;
    }

    #region DataGrid

    public ObservableCollection<WeaponViewModel> Weapons { get; }

    private WeaponViewModel currentWeapon;
    public WeaponViewModel CurrentWeapon
    {
        get { return currentWeapon; }
        set
        {
            currentWeapon = value;
            OnPropertyChanged();
        }
    }

    #endregion DataGrid

    #region ComboBox

    public CollectionView DropDownWeapons { get; } 

    private WeaponViewModel selectedWeapon;
    public WeaponViewModel SelectedWeapon
    {
        get { return selectedWeapon; }
        set
        {
            if (value != null)
            {
                selectedWeapon = value;
                ReplaceCurrentWith(selectedWeapon);
                OnPropertyChanged();
            }
        }
    }

    private void ReplaceCurrentWith(WeaponViewModel requestedWeapon)
    {
        currentWeapon.IsShown = false;
        requestedWeapon.IsShown = true;
        var currentWeaponIndex = Weapons.IndexOf(currentWeapon);
        var requestedWeaponIndex = Weapons.IndexOf(requestedWeapon);
        Weapons.Move(requestedWeaponIndex, currentWeaponIndex);
        DropDownWeapons.Refresh();
    }

    private bool DropDownFilter(object item)
    {
        var weapon = (WeaponViewModel)item;
        return weapon.IsShown == false;
    }

    #endregion ComboBox

    private static IList<WeaponViewModel> GetWeapons()
    {
        var weapons = new List<WeaponViewModel>
        {
            new WeaponViewModel("Assault Rifle", "AR", 30, true),
            new WeaponViewModel("Submachine Gun", "SM", 17, true),
            new WeaponViewModel("Revolver", "RV", 54, true),
            new WeaponViewModel("Shotgun", "AR", 30, true),
            new WeaponViewModel("Sniper", "SN", 63, true),
            new WeaponViewModel("Rocket Launcher", "RL", 300, true),
            new WeaponViewModel("Grenade Launcher", "GL", 200, true),
            new WeaponViewModel("Minigun", "MG", 20, true),
            new WeaponViewModel("Knife", "KN", 10, false),
            new WeaponViewModel("Baseball Bat", "BB", 6, false),
        };
        return weapons;
    }
}

MainWindow.xaml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:WpfApp.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>
    <DataGrid ItemsSource="{Binding Weapons}" SelectedItem="{Binding CurrentWeapon}"
              AutoGenerateColumns="False">
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsShown}" Value="False">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Weapons">
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                            ItemsSource="{Binding DropDownWeapons}"
                            SelectedItem="{Binding SelectedWeapon}"
                            DisplayMemberPath="Name"
                            IsEditable="False" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" />
            <DataGridTextColumn Header="AB" Binding="{Binding Abbreviation}" />
            <DataGridTextColumn Header="Damage"  Binding="{Binding Damage}" />
        </DataGrid.Columns>
    </DataGrid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...