简体   繁体   中英

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

This is related to Databinding the DataGrid column header in code but it asks the opposite question: "How do I do it in XAML?", not "How do I do it in code?"

I've constructed this 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>

and this 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"}.");
}

The binding works as expected for DataGrid.ItemsSource , but no binding I've constructed works for DataGridColumn.SortDirection . When clicking the column header ("Click Me"), I expect to see both message boxes, but only one appears.


I can put BindingOperations.SetBinding(column, DataGridColumn.SortDirectionProperty, new Binding(nameof(SortDirection)) { Source = this, Mode = BindingMode.TwoWay }); in the constructor to set up the binding as expected, but I've been brought up to believe that bindings should be constructed in XAML, not in code.

A DataGridColumn is not a visual element and doesn't inherit any DataContext . You could implement a binding proxy to work around this. See this answer and this blog post for examples and more information.

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

As a side note, there is nothing wrong with setting up bindings programmatically. It doesn't break the MVVM design pattern. XAML is a markup language. You can implement an entire view programmatically if you really want to. Trying to do everything in XAML just for the sake of it is generally considered an anti-pattern. A (fairly) complex view usually needs code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM