C# 限制listview中的列不大于X(NotifyPropertyChanged不工作)

C# 限制listview中的列不大于X(NotifyPropertyChanged不工作),c#,wpf,data-binding,observablecollection,inotifypropertychanged,C#,Wpf,Data Binding,Observablecollection,Inotifypropertychanged,以下是我键入数字时程序的行为方式: /// <summary> /// Represent each row in listview /// </summary> public class Item : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String in

以下是我键入数字时程序的行为方式:

/// <summary>
/// Represent each row in listview
/// </summary>
public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    void UpdateSum()
    {
        Sum = Col1;// + col2 + col3 etc
    }

    decimal _Col1;
    public decimal Col1 //                                         ||
    {                   //                                         ||
        get             //                                         ||
        {               //                                         ||              
            return _Col1; //                                       ||                              
        }                 //                                       ||              
        set               //                                       ||                
        {                 //                                    \  ||   /                        
            if (value > 100)  //                                 \ || /                                
            {                 //                                   \/                  
                Col1 = 100;  // !!!!!!!!!!!!!!!!!!!!!  HERE why does the listview does't update!!!!!!!!
                NotifyPropertyChanged("Col1");
            }else
            {
                _Col1 = value;
            }
            UpdateSum();
            NotifyPropertyChanged("Col1");
        }
    }

    decimal _Sum;
    public decimal Sum
    {
        get
        {
            return _Sum;
        }
        set
        {
            _Sum = value;

            NotifyPropertyChanged("Sum");
        }
    }
}

我有一个绑定到可观察集合的listview。这是我的代码:(你可以跳过这部分,类非常简单)

类项目:

/// <summary>
/// Represent each row in listview
/// </summary>
public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    void UpdateSum()
    {
        Sum = Col1;// + col2 + col3 etc
    }

    decimal _Col1;
    public decimal Col1 //                                         ||
    {                   //                                         ||
        get             //                                         ||
        {               //                                         ||              
            return _Col1; //                                       ||                              
        }                 //                                       ||              
        set               //                                       ||                
        {                 //                                    \  ||   /                        
            if (value > 100)  //                                 \ || /                                
            {                 //                                   \/                  
                Col1 = 100;  // !!!!!!!!!!!!!!!!!!!!!  HERE why does the listview does't update!!!!!!!!
                NotifyPropertyChanged("Col1");
            }else
            {
                _Col1 = value;
            }
            UpdateSum();
            NotifyPropertyChanged("Col1");
        }
    }

    decimal _Sum;
    public decimal Sum
    {
        get
        {
            return _Sum;
        }
        set
        {
            _Sum = value;

            NotifyPropertyChanged("Sum");
        }
    }
}
//
///表示listview中的每一行
/// 
公共类项目:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged(字符串信息)
{
if(PropertyChanged!=null)
{
PropertyChanged(此,新PropertyChangedEventArgs(信息));
}
}
void UpdateSum()
{
Sum=Col1;//+col2+col3等
}
十进制_Col1;
公共十进制Col1//||
{                   //                                         ||
获取//||
{               //                                         ||              
返回_Col1;/| |
}                 //                                       ||              
设置//| |
{                 //                                    \  ||   /                        
如果(值>100)/\\\|
{                 //                                   \/                  
Col1=100;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这里为什么列表视图不更新!!!!!!!!
NotifyPropertyChanged(“Col1”);
}否则
{
_Col1=值;
}
UpdateSum();
NotifyPropertyChanged(“Col1”);
}
}
十进制和;
公共十进制和
{
得到
{
返回(u)和;;
}
设置
{
_总和=价值;
通知财产变更(“金额”);
}
}
}
代码隐藏

using System;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public ObservableCollection<Item> Collection = new ObservableCollection<Item>();

        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {

            Collection.Add(new Item());
            listView2.DataContext = Collection;
            listView2.ItemsSource = Collection;
            listView2.IsSynchronizedWithCurrentItem = true;
        }
    }
}
使用系统;
使用System.Windows;
使用系统组件模型;
使用System.Collections.ObjectModel;
命名空间WpfApplication3
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共ObservableCollection集合=新ObservableCollection();
公共主窗口()
{
初始化组件();
this.Loaded+=新的RoutedEventHandler(主窗口已加载);
}
已加载无效主窗口(对象发送器、路由目标)
{
集合。添加(新项());
listView2.DataContext=集合;
listView2.ItemsSource=集合;
listView2.IsSynchronizedWithCurrentItem=true;
}
}
}
xaml中的列表视图:

/// <summary>
/// Represent each row in listview
/// </summary>
public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    void UpdateSum()
    {
        Sum = Col1;// + col2 + col3 etc
    }

    decimal _Col1;
    public decimal Col1 //                                         ||
    {                   //                                         ||
        get             //                                         ||
        {               //                                         ||              
            return _Col1; //                                       ||                              
        }                 //                                       ||              
        set               //                                       ||                
        {                 //                                    \  ||   /                        
            if (value > 100)  //                                 \ || /                                
            {                 //                                   \/                  
                Col1 = 100;  // !!!!!!!!!!!!!!!!!!!!!  HERE why does the listview does't update!!!!!!!!
                NotifyPropertyChanged("Col1");
            }else
            {
                _Col1 = value;
            }
            UpdateSum();
            NotifyPropertyChanged("Col1");
        }
    }

    decimal _Sum;
    public decimal Sum
    {
        get
        {
            return _Sum;
        }
        set
        {
            _Sum = value;

            NotifyPropertyChanged("Sum");
        }
    }
}


无论如何,为什么当我更新
Col1=100
时,它不会在列表视图中更新!还要注意,总和是100,而不是1000。 我不希望第1列大于某个数字x。在我的实际程序中,数字是动态变化的,我在Item类中计算它

我怎样才能解决这个问题



编辑 我发现了一些有趣的东西。。。如果我开始输入不同的数字,看看会发生什么:在本例中,我将只键入5:

它在步骤3中工作!!!
一旦等于100,它就停止工作了…

我让它工作了!!!我改变了:

 Text="{Binding Col1, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
用于:


但是我需要在文本框更改时更新属性,所以这可能是其他人的解决方案…基本上,您正在尝试在数据绑定期间更改属性值。问题是WPF试图变得聪明,不监听在数据绑定期间引发的属性更改。 这是一个众所周知的问题,有许多解决方法:

尽管MS在WPF4.0中进行了一些修复,请参见:

但是我做了一些快速测试,但是由于
UpdateSourceTrigger=PropertyChanged
,没有一个在您的案例中起作用

然而,我可以想出一个非常肮脏的解决办法,即“工作”:

见it行动:

注意:输入第三个5后,光标将移动到文本框的开头,如果您输入下一个5,光标将保持在那里


我不认为上面提到的代码应该是解决方案,我只是玩了一点。我认为您应该使用
UpdateSourceTrigger=LostFocus
并从文本框
TextChanged
事件手动进行绑定。。。但是,恐怕没有干净的解决方案来解决您的问题。

基本上,文本框中存在一个错误,如果您以这种方式更改绑定值,它只会更新文本框的第一个字符。例如,如果输入1005,它会将前3个字符更新为100(但忽略5个字符)

解决这个问题很简单,我为您的Item类添加了另一个属性,并稍微更改了TextBox绑定:

public class Item : INotifyPropertyChanged
{
    private int maxValue = 100;
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    void UpdateSum()
    {
        Sum = Col1;// + col2 + col3 etc
    }

    decimal _Col1;
    public decimal Col1 
    {                  
        get            
        {                         
            return _Col1;                             
        }                          
        set                       
        {                       
            if (value > maxValue)                                
            {                                
                Col1 = maxValue; 
                NotifyPropertyChanged("Col1");
            }
            else
            {
                _Col1 = value;
            }
            UpdateSum();
            NotifyPropertyChanged("Col1");
        }
    }

    public int MaxValueWidth
    {
        get
        {
            var tmp = (int)Math.Log10(maxValue) + 1;
            return tmp;
        }
    }

    decimal _Sum;
    public decimal Sum
    {
        get
        {
            return _Sum;
        }
        set
        {
            _Sum = value;
            NotifyPropertyChanged("Sum");
        }
    }
}
请注意,我添加了一个属性,该属性根据最大值计算文本框的最大字符数

不,我所做的就是添加绑定

<DataTemplate>
    <TextBox Width="200" Text="{Binding Col1, UpdateSourceTrigger=PropertyChanged}" MaxLength="{Binding MaxValueWidth}"></TextBox>
</DataTemplate>


您不应该将属性更改两次,最后的一次就足够了。这对您没有什么帮助,但是在您的Col1设置程序中,将
if(value>100){Col1=100;..
更改为
if(value>100){Col1=100;..
我应该包装
//HACK:根据条件取消bindig if(value>100)抛出n