如何使用 XAML 在 WPF 中对 DataGridColumn.SortDirection 进行数据绑定?

How do I databind DataGridColumn.SortDirection in WPF, using XAML?

这与 Databinding the DataGrid column header in code 有关,但它提出了相反的问题:“我如何在 XAML 中执行此操作?”,而不是“我如何在代码中执行此操作?”

我构建了这个MainWindow.xaml

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <DataGrid AutoGenerateColumns="False" CanUserSortColumns="True" Sorting="DataGrid_Sorting" Margin="5" ItemsSource="{Binding ItemsSource}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Value}" SortDirection="{Binding SortDirection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Mode=TwoWay}" Header="Click Me" x:Name="column"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

和这个MainWindow.xaml.cs

using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;

public partial class MainWindow : Window
{
    private ListSortDirection? _sortDirection;
    public ListSortDirection? SortDirection
    {
        get => _sortDirection;
        set
        {
            // I expect this message box to appear, but it doesn't.
            MessageBox.Show($"Setting sort direction to {value?.ToString() ?? "null"}");
            _sortDirection = value;
        }
    }

    public IEnumerable<object> ItemsSource { get; } = new[] { 1, 2, 3, 4, 5 }.Select(x => new { Value = x }).ToList();

    public MainWindow() => InitializeComponent();

    private void DataGrid_Sorting(object sender, System.Windows.Controls.DataGridSortingEventArgs e)
        => MessageBox.Show($"Sorting grid.\nColumn sort direction was {column.SortDirection?.ToString() ?? "null"}.");
}

DataGrid.ItemsSource 的绑定按预期工作,但我构建的绑定没有为 DataGridColumn.SortDirection 工作。单击列 header(“单击我”)时,我希望看到两个消息框,但只出现一个。


我可以将 BindingOperations.SetBinding(column, DataGridColumn.SortDirectionProperty, new Binding(nameof(SortDirection)) { Source = this, Mode = BindingMode.TwoWay }); 放入构造函数中以按预期设置绑定,但我一直认为绑定应该在 XAML 中构建,而不是在代码中构建。

A​​ DataGridColumn 不是视觉元素,不继承任何 DataContext。您可以实施绑定代理来解决此问题。有关示例和更多信息,请参阅 this answer and this 博客 post。

but I've been brought up to believe that bindings should be constructed in XAML, not in code.

附带说明一下,以编程方式设置绑定并没有错。它不会破坏 MVVM 设计模式。 XAML 是一种 标记 语言。如果您确实愿意,可以通过编程方式实现整个视图。在 XAML 中尝试做 一切 只是为了它通常被认为是 anti-pattern。 (相当)复杂的视图通常需要代码。