Использование привязок для управления порядком столбцов в DataGrid - PullRequest
12 голосов
/ 24 января 2010

Задача

У меня есть WPF Toolkit DataGrid, и я хотел бы иметь возможность переключаться между несколькими предустановленными порядками столбцов. Это проект MVVM, поэтому порядки столбцов хранятся в ViewModel. Проблема в том, что я не могу заставить привязки работать для свойства DisplayIndex. Что бы я ни пытался, включая сладкий метод в этом уроке Джоша Смита , я получаю:

Значение DisplayIndex для столбца DataGridColumn с идентификатором заголовка находится вне диапазона. DisplayIndex должен быть больше или равен 0 и меньше, чем Columns.Count. Имя параметра: displayIndex. Фактическое значение было -1.

Есть ли обходной путь для этого?

Я включил мой тестовый код ниже. Пожалуйста, дайте мне знать, если вы видите какие-либо проблемы с ним.


Код модели представления

public class MainViewModel
{
    public List<Plan> Plans { get; set; }
    public int IdDisplayIndex { get; set; }
    public int NameDisplayIndex { get; set; }
    public int DescriptionDisplayIndex { get; set; }

    public MainViewModel()
    {
        Initialize();
    }

    private void Initialize()
    {
        IdDisplayIndex = 1;
        NameDisplayIndex = 2;
        DescriptionDisplayIndex = 0;
        Plans = new List<Plan>
        {
            new Plan { Id = 1, Name = "Primary", Description = "Likely to work." },
            new Plan { Id = 2, Name = "Plan B", Description = "Backup plan." },
            new Plan { Id = 3, Name = "Plan C", Description = "Last resort." }
        };
    }
}

План класса

public class Plan
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

Код окна - здесь используется DataContextSpy Джоша Смита

<Window
    x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:mwc="http://schemas.microsoft.com/wpf/2008/toolkit"
    Title="Main Window" Height="300" Width="300">
    <Grid>
        <mwc:DataGrid ItemsSource="{Binding Plans}" AutoGenerateColumns="False">
            <mwc:DataGrid.Resources>
                <local:DataContextSpy x:Key="spy" />
            </mwc:DataGrid.Resources>
            <mwc:DataGrid.Columns>
                <mwc:DataGridTextColumn
                    Header="ID" 
                    Binding="{Binding Id}"
                    DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex}" />
                <mwc:DataGridTextColumn
                    Header="Name"
                    Binding="{Binding Name}"
                    DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.NameDisplayIndex}" />
                <mwc:DataGridTextColumn
                    Header="Description"
                    Binding="{Binding Description}"
                    DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.DescriptionDisplayIndex}" />
            </mwc:DataGrid.Columns>
        </mwc:DataGrid>
    </Grid>
</Window>

Примечание: Если я просто использую простые числа для DisplayIndex, все работает нормально, поэтому проблема определенно связана с привязками.


Обновление 5/1/2010

Я просто занимался небольшим обслуживанием своего проекта и заметил, что когда я его запустил, проблема, которую я обсуждаю в этом посте, вернулась. Я знал, что это сработало в прошлый раз, когда я запускал его, поэтому я в конечном итоге сузил проблему до факта, что я установил более новую версию WPF Toolkit (февраль '10). Когда я вернулся к июньской версии 2009 года, все снова заработало нормально. Итак, сейчас я делаю то, что должен был сделать в первую очередь: я включил WPFToolkit.dll, который работает в папке с моими решениями, и включил его в систему контроля версий. Прискорбно, однако, что в новом инструментарии произошли серьезные изменения.

Ответы [ 3 ]

12 голосов
/ 21 января 2011

Установите FallbackValue=<idx> в привязке DisplayIndex, где <idx> - индекс вашего столбца. Например:

DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex, FallbackValue=0}" />
4 голосов
/ 24 января 2010

(Мой предыдущий ответ был не в порядке - поэтому я удалил его - я попытаюсь ответить снова после воспроизведения ошибки на моей машине)

Проблема, с которой вы сталкиваетесь, связана с тем фактом, что при первой оценке привязок свойство DataContext по-прежнему имеет значение null. Это по какой-то странной причине, пока неизвестной мне, приводит к тому, что привязка оценивается в -1. Однако, если вы обязательно установите DataContext до , привязки будут оценены, все будет в порядке. К сожалению, это может быть возможно только при выделении кода - следовательно, во время выполнения, а не во время разработки. Так что во время разработки я до сих пор не знаю, как обойти ошибку.

Для этого установите свойство DataContext окна перед вызовом на InitializeComponent, таким образом:

public MainWindow()
{
    DataContext = new MainViewModel();
    InitializeComponent();
}

Надеюсь, это поможет.

1 голос
/ 01 июля 2014

Я добавляю это как ответ, так как я пока не могу комментировать. Причина, по которой значение DisplayIndex установлено в -1:

Свойство DisplayIndex имеет значение по умолчанию -1, прежде чем оно будет добавлено в коллекцию DataGrid.Columns. Это значение обновляется, когда столбец добавляется в DataGrid.

DataGrid требует, чтобы свойство DisplayIndex каждого столбца должно быть уникальным целым числом от 0 до Кол-во столбцов -1. Следовательно, когда изменяется DisplayIndex одного столбца, изменение обычно вызывает изменение DisplayIndex других столбцов.

Ограничения на значение DisplayIndex применяются Механизм ValidateValueCallback. Если вы пытаетесь установить значение, которое недопустимый, исключение во время выполнения.

Когда значение свойства DisplayIndex изменяется, Событие DataGrid.ColumnDisplayIndexChanged возникает.

Источник: http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.datagridcolumn.displayindex(v=vs.100).aspx

Итак, я полагаю, что можно проверить это значение при его изменении с помощью вышеупомянутого события.

Решение, упомянутое Авиад, не сработало для меня. У меня есть свой Datagrid в UserControl, такой же как OP, и изменение порядка конструктора ViewModel, объявление DataContext и метод InitializeComponent() не помогли.

Метод Пакмана FallbackValue работал очень хорошо, с другой стороны.

...