WPF 数据网格绑定与自定义列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18152097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:24:50  来源:igfitidea点击:

WPF datagrid binding with custom columns

c#.netwpfmvvmwpfdatagrid

提问by rupareliab

Currently I am working on WPF application (with MVVM) in which I am displaying data in the DataGridView.

目前我正在开发 WPF 应用程序(使用 MVVM),其中我在DataGridView.

<DataGrid RowHeaderWidth="0" ItemsSource="{Binding PartsList,UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Item Name" IsReadOnly="True" Width="*" Binding="{Binding ProductName}"></DataGridTextColumn>
        <DataGridTextColumn Header="Model Name" IsReadOnly="True" Width="*" Binding="{Binding CarModelName}"></DataGridTextColumn>
        <DataGridTextColumn Header="Company Name" IsReadOnly="True" Width="*" Binding="{Binding CompanName}"></DataGridTextColumn>
        <DataGridTextColumn Header="Price" IsReadOnly="True" Width="*" Binding="{Binding Rate}">
    </DataGrid.Columns>
</DataGrid>

Here PartsList is an ObservableCollectionof entity Part.

这里的 PartsList 是ObservableCollection实体 Part 的一个。

Now I want to add custom column to the DataGridwhich shows discount and another column which shows net amount. How can I do this?

现在我想将自定义列添加到DataGrid显示折扣的列和显示净额的另一列。我怎样才能做到这一点?

Please give a good idea to do this as I need to work with thousands of records so performance is very important for me.

请给出一个好主意,因为我需要处理数千条记录,因此性能对我来说非常重要。

Thank you in advance.

先感谢您。

回答by yo chauhan

Try to add columns on the Loadedevent of DataGrid:

尝试在以下Loaded事件中添加列DataGrid

private void DataGrid_Loaded_1(object sender, RoutedEventArgs e)
{
    dataGrid.Columns.Add((DataGridTextColumn)this.Resources["DiscountColumn"]);
    dataGrid.Columns.Add((DataGridTextColumn)this.Resources["NetAmountColumn"]);

    //Alternatively you can create columns in .cs like

    dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Dicount", Binding = new Binding("Discount") });
    dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Net Amount", Binding = new Binding("NetAmount") });
}
<Window.Resources>
    <DataGridTextColumn x:Key="DiscountColumn" Header="Discount" IsReadOnly="True" Width="*" Binding="{Binding Discount}"/>
    <DataGridTextColumn x:Key="NetAmountColumn" Header="Net Amount" IsReadOnly="True" Width="*" Binding="{Binding NetAmount}"/>
</Window.Resources>

<DataGrid RowHeaderWidth="0" x:Name="dataGrid" Loaded="DataGrid_Loaded_1" />

回答by Bijington

This is an old post but I have done something similar using MVVMand WPFso thought I would through my two pennies worth in.

这是一篇旧帖子,但我使用过类似的东西MVVMWPF所以我想我会花掉我的两分钱。

I cannot give any real indication of how it will perform however we haven't seen any real issues with displaying around a thousand objects in the ItemSource.

我无法给出任何关于它将如何执行的真实指示,但是我们还没有看到在ItemSource.

Apologies it is going to be a lengthy display of code but I will try to break it down so it is easy to follow.

抱歉,这将是一段冗长的代码显示,但我会尝试将其分解,以便于理解。

Ultimately what you need to do is create an Attached Behavior.

最终您需要做的是创建一个Attached Behavior

Here is mine:

这是我的:

Behavior class

行为类

This does the core work in creating the actual columns and add them to your DataGridbased on the ColumnsSourcethat you bind to it.

这完成了创建实际列的核心工作,并DataGrid根据ColumnsSource您绑定到的列将它们添加到您的列中。

public class DataGridColumnCollectionBehavior
{
    private object columnsSource;
    private DataGrid dataGrid;

    public DataGridColumnCollectionBehavior(DataGrid dataGrid)
    {
        this.dataGrid = dataGrid;
    }

    public object ColumnsSource
    {
        get { return this.columnsSource; }
        set
        {
            object oldValue = this.columnsSource;
            this.columnsSource = value;
            this.ColumnsSourceChanged(oldValue, this.columnsSource);
        }
    }

    public string DisplayMemberFormatMember { get; set; }

    public string DisplayMemberMember { get; set; }

    public string FontWeightBindingMember { get; set; }

    public string FontWeightMember { get; set; }

    public string HeaderTextMember { get; set; }

    public string IsEditableMember { get; set; }

    public string SortMember { get; set; }

    public string TextAlignmentMember { get; set; }

    public string TextColourMember { get; set; }

    public string WidthMember { get; set; }

    private void AddHandlers(ICollectionView collectionView)
    {
        collectionView.CollectionChanged += this.ColumnsSource_CollectionChanged;
    }

    private void ColumnsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        ICollectionView view = sender as ICollectionView;

        if (this.dataGrid == null)
        {
            return;
        }

        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                for (int i = 0; i < e.NewItems.Count; i++)
                {
                    DataGridColumn column = CreateColumn(e.NewItems[i]);
                    dataGrid.Columns.Insert(e.NewStartingIndex + i, column);
                }
                break;
            case NotifyCollectionChangedAction.Move:
                List<DataGridColumn> columns = new List<DataGridColumn>();

                for (int i = 0; i < e.OldItems.Count; i++)
                {
                    DataGridColumn column = dataGrid.Columns[e.OldStartingIndex + i];
                    columns.Add(column);
                }

                for (int i = 0; i < e.NewItems.Count; i++)
                {
                    DataGridColumn column = columns[i];
                    dataGrid.Columns.Insert(e.NewStartingIndex + i, column);
                }
                break;
            case NotifyCollectionChangedAction.Remove:
                for (int i = 0; i < e.OldItems.Count; i++)
                {
                    dataGrid.Columns.RemoveAt(e.OldStartingIndex);
                }
                break;
            case NotifyCollectionChangedAction.Replace:
                for (int i = 0; i < e.NewItems.Count; i++)
                {
                    DataGridColumn column = CreateColumn(e.NewItems[i]);

                    dataGrid.Columns[e.NewStartingIndex + i] = column;
                }
                break;
            case NotifyCollectionChangedAction.Reset:
                dataGrid.Columns.Clear();
                CreateColumns(sender as ICollectionView);
                break;
            default:
                break;
        }
    }

    private void ColumnsSourceChanged(object oldValue, object newValue)
    {
        if (this.dataGrid != null)
        {
            dataGrid.Columns.Clear();

            if (oldValue != null)
            {
                ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);

                if (view != null)
                {
                    this.RemoveHandlers(view);
                }
            }

            if (newValue != null)
            {
                ICollectionView view = CollectionViewSource.GetDefaultView(newValue);

                if (view != null)
                {
                    this.AddHandlers(view);

                    this.CreateColumns(view);
                }
            }
        }
    }

    private DataGridColumn CreateColumn(object columnSource)
    {
        DataGridColumn column = new DataGridTemplateColumn();

        var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
        ((DataGridTemplateColumn)column).CellTemplate = new DataTemplate { VisualTree = textBlockFactory };
        textBlockFactory.SetValue(TextBlock.MarginProperty, new Thickness(3));

        if (!string.IsNullOrWhiteSpace(this.FontWeightBindingMember))
        {
            string propertyName = GetPropertyValue(columnSource, this.FontWeightBindingMember) as string;

            textBlockFactory.SetBinding(TextBlock.FontWeightProperty, new Binding(propertyName));
        }
        else if (!string.IsNullOrWhiteSpace(this.FontWeightMember))
        {
            textBlockFactory.SetValue(TextBlock.FontWeightProperty, (FontWeight)GetPropertyValue(columnSource, this.FontWeightMember));
        }

        if (!string.IsNullOrWhiteSpace(this.SortMember))
        {
            column.SortMemberPath = GetPropertyValue(columnSource, this.SortMember) as string;
        }

        if (!string.IsNullOrEmpty(this.DisplayMemberMember))
        {
            string propertyName = GetPropertyValue(columnSource, this.DisplayMemberMember) as string;

            string format = null;

            if (!string.IsNullOrEmpty(this.DisplayMemberFormatMember))
            {
                format = GetPropertyValue(columnSource, this.DisplayMemberFormatMember) as string;
            }

            if (string.IsNullOrEmpty(format))
            {
                format = "{0}";
            }

            textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding(propertyName) { StringFormat = format });

            // If there is no sort member defined default to the display member.
            if (string.IsNullOrWhiteSpace(column.SortMemberPath))
            {
                column.SortMemberPath = propertyName;
            }
        }

        if (!string.IsNullOrWhiteSpace(this.TextAlignmentMember))
        {
            textBlockFactory.SetValue(TextBlock.TextAlignmentProperty, GetPropertyValue(columnSource, this.TextAlignmentMember));
        }

        if (!string.IsNullOrEmpty(this.HeaderTextMember))
        {
            column.Header = GetPropertyValue(columnSource, this.HeaderTextMember);
        }

        if (!string.IsNullOrWhiteSpace(this.TextColourMember))
        {
            string propertyName = GetPropertyValue(columnSource, this.TextColourMember) as string;
            textBlockFactory.SetBinding(TextBlock.ForegroundProperty, new Binding(propertyName));
        }

        if (!string.IsNullOrEmpty(this.WidthMember))
        {
            double width = (double)GetPropertyValue(columnSource, this.WidthMember);
            column.Width = width;
        }

        return column;
    }

    private void CreateColumns(ICollectionView collectionView)
    {
        foreach (object item in collectionView)
        {
            DataGridColumn column = this.CreateColumn(item);

            this.dataGrid.Columns.Add(column);
        }
    }

    private object GetPropertyValue(object obj, string propertyName)
    {
        object returnVal = null;

        if (obj != null)
        {
            PropertyInfo prop = obj.GetType().GetProperty(propertyName);

            if (prop != null)
            {
                returnVal = prop.GetValue(obj, null);
            }
        }

        return returnVal;
    }

    private void RemoveHandlers(ICollectionView collectionView)
    {
        collectionView.CollectionChanged -= this.ColumnsSource_CollectionChanged;
    }
}

Accessor class

存取器类

This is the class that you use within your XAML files in order to create the Bindings.

这是您在 XAML 文件中用于创建Bindings 的类。

public static class DataGridColumnCollection
{
    public static readonly DependencyProperty ColumnCollectionBehaviourProperty =
        DependencyProperty.RegisterAttached("ColumnCollectionBehaviour", typeof(DataGridColumnCollectionBehaviour), typeof(DataGridColumnCollection), new UIPropertyMetadata(null));

    public static readonly DependencyProperty ColumnsSourceProperty =
        DependencyProperty.RegisterAttached("ColumnsSource", typeof(object), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.ColumnsSourcePropertyChanged));

    public static readonly DependencyProperty DisplayMemberFormatMemberProperty =
        DependencyProperty.RegisterAttached("DisplayMemberFormatMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.DisplayMemberFormatMemberChanged));

    public static readonly DependencyProperty DisplayMemberMemberProperty =
        DependencyProperty.RegisterAttached("DisplayMemberMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.DisplayMemberMemberChanged));

    public static readonly DependencyProperty FontWeightBindingMemberProperty =
        DependencyProperty.RegisterAttached("FontWeightBindingMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.FontWeightBindingMemberChanged));

    public static readonly DependencyProperty FontWeightMemberProperty =
        DependencyProperty.RegisterAttached("FontWeightMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.FontWeightMemberChanged));

    public static readonly DependencyProperty IsEditableMemberProperty =
        DependencyProperty.RegisterAttached("IsEditableMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.IsEditableMemberChanged));

    public static readonly DependencyProperty HeaderTextMemberProperty =
        DependencyProperty.RegisterAttached("HeaderTextMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.HeaderTextMemberChanged));

    public static readonly DependencyProperty SortMemberProperty =
        DependencyProperty.RegisterAttached("SortMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.SortMemberChanged));

    public static readonly DependencyProperty TextAlignmentMemberProperty =
        DependencyProperty.RegisterAttached("TextAlignmentMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.TextAlignmentMemberChanged));

    public static readonly DependencyProperty TextColourMemberProperty =
        DependencyProperty.RegisterAttached("TextColourMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.TextColourMemberChanged));

    public static readonly DependencyProperty WidthMemberProperty =
        DependencyProperty.RegisterAttached("WidthMember", typeof(string), typeof(DataGridColumnCollection), new UIPropertyMetadata(null, DataGridColumnCollection.WidthMemberChanged));

    public static DataGridColumnCollectionBehaviour GetColumnCollectionBehaviour(DependencyObject obj)
    {
        return (DataGridColumnCollectionBehaviour)obj.GetValue(ColumnCollectionBehaviourProperty);
    }

    public static void SetColumnCollectionBehaviour(DependencyObject obj, DataGridColumnCollectionBehaviour value)
    {
        obj.SetValue(ColumnCollectionBehaviourProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static object GetColumnsSource(DependencyObject obj)
    {
        return (object)obj.GetValue(ColumnsSourceProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static void SetColumnsSource(DependencyObject obj, ObservableCollection<DataGridColumn> value)
    {
        obj.SetValue(ColumnsSourceProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetDisplayMemberFormatMember(DependencyObject obj)
    {
        return (string)obj.GetValue(DisplayMemberFormatMemberProperty);
    }

    public static void SetDisplayMemberFormatMember(DependencyObject obj, string value)
    {
        obj.SetValue(DisplayMemberFormatMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetDisplayMemberMember(DependencyObject obj)
    {
        return (string)obj.GetValue(DisplayMemberMemberProperty);
    }

    public static void SetDisplayMemberMember(DependencyObject obj, string value)
    {
        obj.SetValue(DisplayMemberMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetFontWeightBindingMember(DependencyObject obj)
    {
        return (string)obj.GetValue(FontWeightBindingMemberProperty);
    }

    public static void SetFontWeightBindingMember(DependencyObject obj, string value)
    {
        obj.SetValue(FontWeightBindingMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetFontWeightMember(DependencyObject obj)
    {
        return (string)obj.GetValue(FontWeightMemberProperty);
    }

    public static void SetFontWeightMember(DependencyObject obj, string value)
    {
        obj.SetValue(FontWeightMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetTextAlignmentMember(DependencyObject obj)
    {
        return (string)obj.GetValue(TextAlignmentMemberProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static void SetTextAlignmentMember(DependencyObject obj, string value)
    {
        obj.SetValue(TextAlignmentMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetTextColourMember(DependencyObject obj)
    {
        return (string)obj.GetValue(TextColourMemberProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static void SetTextColourMember(DependencyObject obj, string value)
    {
        obj.SetValue(TextColourMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static string GetHeaderTextMember(DependencyObject obj)
    {
        return (string)obj.GetValue(HeaderTextMemberProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static void SetHeaderTextMember(DependencyObject obj, string value)
    {
        obj.SetValue(HeaderTextMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetWidthMember(DependencyObject obj)
    {
        return (string)obj.GetValue(WidthMemberProperty);
    }

    public static void SetWidthMember(DependencyObject obj, string value)
    {
        obj.SetValue(WidthMemberProperty, value);
    }

    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static string GetSortMember(DependencyObject obj)
    {
        return (string)obj.GetValue(SortMemberProperty);
    }

    public static void SetSortMember(DependencyObject obj, string value)
    {
        obj.SetValue(SortMemberProperty, value);
    }

    private static void ColumnsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).ColumnsSource = e.NewValue;
    }

    private static void DisplayMemberFormatMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).DisplayMemberFormatMember = e.NewValue as string;
    }

    private static void DisplayMemberMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).DisplayMemberMember = e.NewValue as string;
    }

    private static void FontWeightBindingMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).FontWeightBindingMember = e.NewValue as string;
    }

    private static void FontWeightMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).FontWeightMember = e.NewValue as string;
    }

    private static void IsEditableMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).IsEditableMember = e.NewValue as string;
    }

    private static void HeaderTextMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).HeaderTextMember = e.NewValue as string;
    }

    private static void SortMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).SortMember = e.NewValue as string;
    }

    private static void TextAlignmentMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).TextAlignmentMember = e.NewValue as string;
    }

    private static void TextColourMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).TextColourMember = e.NewValue as string;
    }

    private static void WidthMemberChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        DataGridColumnCollection.GetOrCreateBehaviour(sender).WidthMember = e.NewValue as string;
    }

    private static DataGridColumnCollectionBehaviour GetOrCreateBehaviour(DependencyObject source)
    {
        DataGridColumnCollectionBehaviour behaviour = DataGridColumnCollection.GetColumnCollectionBehaviour(source);

        if (behaviour == null)
        {
            behaviour = new DataGridColumnCollectionBehaviour(source as DataGrid);

            DataGridColumnCollection.SetColumnCollectionBehaviour(source, behaviour);
        }

        return behaviour;
    }
}

Example XAML usage

XAML 用法示例

Now we actually get on to using it.

现在我们实际上开始使用它。

<DataGrid behaviors:DataGridColumnCollection.ColumnsSource="{Binding ColumnHeaders}"
          behaviors:DataGridColumnCollection.DisplayMemberFormatMember="Format"                         behaviors:DataGridColumnCollection.DisplayMemberMember="DisplayMember"
                      behaviors:DataGridColumnCollection.FontWeightBindingMember="FontWeightMember"
                      behaviors:DataGridColumnCollection.HeaderTextMember="Header"
                      behaviors:DataGridColumnCollection.SortMember="SortMember"
                      behaviors:DataGridColumnCollection.TextAlignmentMember="TextAlignment"
                      behaviors:DataGridColumnCollection.TextColourMember="TextColourMember"
                      behaviors:DataGridColumnCollection.WidthMember="Width"
                      ItemsSource="{Binding Items}">

Column Header class

列标题类

This is just my 'simple' class that describes a column.

这只是我描述列的“简单”类。

public class ColumnHeaderDescriptor
{
    public string DisplayMember { get; set; }

    public string FontWeightMember { get; set; }

    public string Format { get; set; }

    public string Header { get; set; }

    public string SortMember { get; set; }

    public TextAlignment TextAlignment { get; set; }

    public string TextColourMember { get; set; }

    public double Width { get; set; }
}

Instantiating the columns

实例化列

And this is how I create them.

这就是我创建它们的方式。

this.ColumnHeaders.Add(new ColumnHeaderDescriptor { Header = Properties.Resources.Name, DisplayMember = "ItemName", Width = 250 });
this.ColumnHeaders.Add(new ColumnHeaderDescriptor { Header = Properties.Resources.ManufPartNumber, DisplayMember = "ManufPartNumber", Width = 150 });
this.ColumnHeaders.Add(new ColumnHeaderDescriptor { Header = Properties.Resources.LastUnitPrice, DisplayMember = "UnitPriceString", SortMember = "UnitPrice", Width = 90 });
this.ColumnHeaders.Add(new ColumnHeaderDescriptor { Header = Properties.Resources.AssetType, DisplayMember = "AssetType", Width = 100 });
this.ColumnHeaders.Add(new ColumnHeaderDescriptor { Header = Properties.Resources.Quantity, DisplayMember = "QuantityString", SortMember = "Quantity", Width = 80 });

Conclusion

结论

Now I appreciate that this may not be fully MVVMbut at the end of the day we have to make sacrifices in order to get the job done. This will allow you to dynamically create columns and show different pieces of information from within your View Model.

现在我意识到这可能不完全,MVVM但在一天结束时,我们必须做出牺牲才能完成工作。这将允许您动态创建列并显示视图模型中的不同信息。

My solution is quite a complicated one and I can't take full credit. I am sure I got the starting point from an existing StackOverflow answer however I am at a loss to know where that is now. Given it's complexity by allowing the consumer to determine lots of different things like text colour, etc. this could well be overkill for others solutions and you could remove the unnecessary properties should you not need them.

我的解决方案非常复杂,我不能完全相信。我确信我从现有的 StackOverflow 答案中得到了起点,但是我不知道现在在哪里。考虑到它的复杂性,允许消费者确定许多不同的东西,如文本颜色等。这对于其他解决方案来说可能是过度的,如果你不需要它们,你可以删除不必要的属性。

回答by Hamish Anderson

Assuming you are using Entity Framework for your model; create a partial class of your model with property getters that calculate based on the base class. Ensure that you implement INotifyPropertyChange and then bind the new properties of NetAmount and Discount in new columns.

假设您为模型使用实体框架;使用基于基类计算的属性 getter 创建模型的分部类。确保您实现 INotifyPropertyChange,然后在新列中绑定 NetAmount 和 Discount 的新属性。