【问题标题】:wpf, Datagrid, one column is based on three otherswpf,Datagrid,一列基于其他三列
【发布时间】:2014-10-07 06:01:10
【问题描述】:

我尝试将我的 observablecollection 绑定到数据网格。我想让最后一列基于其他三个(column[n] = column[x]*column[y]*((column[z]+100)/100)) 类似的东西。我的第一个方法是在 get 部分中使用计算来制作属性,但不能让 UpdateSourceTrigger = PropertyChanged 工作。它仅在我转到另一行时更新值。第二种方法是将最后一列 i xaml 绑定到这三个,并在多转换器中进行计算,但不知道如何使该绑定起作用。 我认为第一种方法更好,所以有人可以告诉我为什么UpdateSourceTrigger = PropertyChanged 不起作用,有什么技巧可以让它起作用吗?

编辑

long ilosc;
public long Ilosc { 
    get { 
        return ilosc; 
    } 
    set {
        ilosc = value; Console.WriteLine("ilosc"); NotifyPropertyChanged("CenaBrutto"); 
    } 
}
float cena;
public float Cena { 
    get { 
        return cena; 
    } 
    set {
        cena = value; Console.WriteLine("cena"); NotifyPropertyChanged("CenaBrutto"); 
    } 
}
float vat;
public float Vat { 
    get { 
        return vat; 
    } 
    set {
        vat = value; Console.WriteLine("vat"); NotifyPropertyChanged("CenaBrutto"); 
    } 
}

public float CenaBrutto {
    get {
        return Cena * Ilosc * ((Vat + 100) / 100); ; 
    }
}

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property) {
    if (PropertyChanged != null) {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
}

和xaml代码

<DataGrid ItemsSource="{Binding ElementName=fRoot, Path=Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="dgTU" Grid.Row="1"/>

【问题讨论】:

    标签: c# wpf xaml binding datagrid


    【解决方案1】:

    所以有人可以告诉我为什么“UpdateSourceTrigger=PropertyChanged” 不工作

    您完全误解了UpdateSourceTrigger 的目的,尤其是UpdateSourceTrigger.PropertyChanged。

    在数据绑定场景中,绑定源是一个对象,它为数据绑定提供数据值。另一方面,绑定目标是一个对象,它使用绑定源提供的值。

    WPF 中的典型数据绑定用例假定,视图模型是绑定源,控件是绑定目标。

    UpdateSourceTrigger 设置更新绑定的模式 source(查看示例中的模型),而您的问题与更新 target (DataGrid) 有关。

    有什么技巧可以让它工作吗?

    没有魔法。
    您的视图模型应该实现INotifyPropertyChanged,并且当相关属性之一更改其值时,您必须为您的计算属性引发PropertyChanged 事件。这里是示例:

    public class SomeClass : INotifyPropertyChanged
    {
        public int A
        {
            get { return a; }
            set 
            {
                if (a != value)
                {
                    a = value;
                    OnPropertyChanged("A");
                }
            }
        }
        private int a;
    
        public int B
        {
            get { return b; }
            set 
            {
                if (b != value)
                {
                    b = value;
                    OnPropertyChanged("B");
                }
            }
        }
        private int b;
    
        public int C
        {
            get { return c; }
            private set
            {
                if (c != value)
                {
                    c = value;
                    OnPropertyChanged("C");
                }
            }
        }
        private int c;
    
        // INotifyPropertyChanged implementation
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
    
            // update calculated property
            if (propertyName == "A" || propertyName == "B")
            {
                // this will cause binding target to re-read C value
                C = A + B;
            }
        }
    }
    

    更新。

    如果您的计算属性如下所示:

    public int C
    {
        get { return A + B; }
    }
    

    也就是说,没有设置器,在更改 A 或 B 的值后调用 OnPropertyChanged("C") 就足够了:

    protected virtual void OnPropertyChanged(string propertyName)
    {
        // other stuff
        // update calculated property
        if (propertyName == "A" || propertyName == "B")
        {
            // this will cause binding target to re-read C value
            OnPropertyChanged("C");
        }
    }
    

    更新 2。

    请注意,您将DataGrid 与AutoGenerateColumns="True" 一起使用(这是默认设置)。在这种情况下,数据绑定表达式也使用默认值,对于DataGridTextColumn(将为float 属性生成)UpdateSourceTrigger 是LostFocus。你的建议是对的。

    解决方法是将AutoGenerateColumns设为false,手动设置想要的UpdateSourceTrigger模式:

        <DataGrid ItemsSource="{Binding ElementName=fRoot, Path=Items}" Name="dgTU" Grid.Row="1" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Ilosc, UpdateSourceTrigger=PropertyChanged}"/>
                <DataGridTextColumn Binding="{Binding Cena, UpdateSourceTrigger=PropertyChanged}"/>
                <DataGridTextColumn Binding="{Binding Vat, UpdateSourceTrigger=PropertyChanged}"/>
                <DataGridTextColumn Binding="{Binding CenaBrutto}"/>
            </DataGrid.Columns>
        </DataGrid>
    

    附:一个小笔记。不要使用浮点类型(如float 或double)进行货币计算,请改用decimal。

    【讨论】:

    • 我有“INotifyPropertyChanged”和所有的东西,计算都是在获取 C 属性的一部分。问题是,当我离开行时,数据网格中的所有更改都会转移到我的属性中,就像“UpdateSourceTrigger=LostFocus”一样,我希望它立即工作(就像我在许多其他线程中看到的那样)
    • @RadosławMalinowski:这是因为你没有为C 提高PropertyChanged。我已经更新了答案。
    • 好吧,我很抱歉没有正确指出这一点。在你的更新中,你得到了我的代码中的内容。正如我之前所说,代码运行良好。但是只有当我离开行时它才会更新数据网格中的 C 。我的属性设置器中有控制台写行,当我离开数据网格行时它会触发
    • 好的,首先感谢您的“附注。请注意。不要使用浮点类型(如浮点或双精度)进行货币计算,请改用小数。”其次,autogeneratecolumns false 起到了作用,但是,为整个数据网格设置“UpdateSourceTrigger=PropertyChanged”(当 autogeneratecolumns 为 true 时)不起作用,这不是有点令人困惑吗?
    • @RadosławMalinowski:不,这里没有什么令人困惑的地方。 UpdateSourceTrigger 是特定绑定表达式的属性。 DataGrid 没有对 AutoGenerateColumns 模式进行任何自定义。在您的初始 XAML 中,您已在 DataGrid 的 ItemsSource 属性上设置了 UST。这没有任何意义,因为DataGrid 不能更新它的ItemsSource(它只更新ItemsSource 的内容)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 2014-06-26
    • 2011-02-25
    • 2023-03-15
    • 2018-06-10
    • 2013-08-25
    • 2011-10-13
    相关资源
    最近更新 更多