5

数値を入力したときのプログラムの動作は次のとおりです。

ここに画像の説明を入力

監視可能なコレクションにバインドされたリストビューがあります。これが私のコードです:(クラスは非常に単純なので、この部分を無視してもかまいません)

クラス項目:

/// <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");
        }
    }
}

コードビハインド

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;
        }
    }
}

xaml のリストビュー:

 <ListView Name="listView2" >
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Column1" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Width="200" Text="{Binding Col1, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Sum" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Width="200" Text="{Binding Sum, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

            </GridView>
        </ListView.View>
    </ListView>

Col1=100とにかく、更新するとリストビューで更新されないのはなぜですか! また、合計が 1000 ではなく 100 になることにも注意してください。

column1 を数値 x よりも大きくしたくありません。私の実際のプログラムでは、その数は動的に変化し、Item クラス内で計算します。

どうすればこれを修正できますか?



編集

興味深いことがわかりました...別の数字を入力し始めると、何が起こるか見てみましょう: この例では 5 と入力します:

ここに画像の説明を入力

ステップ3で動作します!!!

100に等しくなると、機能しなくなります...

4

3 に答える 3

1

私はそれを機能させました!!! 私が変更され:

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

為に:

 Text="{Binding Col1, Mode=TwoWay}"

しかし、テキストボックスが変更されたときにプロパティを更新する必要があるため、これは他の誰かにとっての解決策になる可能性があります...

于 2012-04-16T01:36:22.927 に答える
1

基本的に、DataBinding 中にプロパティ値を変更しようとしています。問題は、WPF がスマートになろうとして、DataBinding 中に発生したプロパティの変更をリッスンしないことです。これはよく知られた問題であり、多くの回避策があります。

MS は WPF4.0 でいくつかの修正を行いましたが、参照: WPF 4.0 Data Binding Change (great feature)

しかし、私はいくつかの簡単なテストを行いましたUpdateSourceTrigger=PropertyChanged.

ただし、「機能する」非常に汚れた回避策を思い付くことができます。

public decimal Col1
{
    get { return _Col1; }
    set
    {
        //Change the property value based on condition
        _Col1 = value > 100 ? 100 : value;
        UpdateSum();
        //HACK: Simulate that the property change not fired from the setter
        Dispatcher.CurrentDispatcher
            .BeginInvoke(new Action(() => NotifyPropertyChanged("Col1")));
        //HACK: Cancel the bindig based on condition
        if (value > 100)
            throw new Exception();
    }
}

アクションを見る:

ここに画像の説明を入力

注意: 3 番目の 5 を入力した後、カーソルは TextBox の先頭に移動し、次の 5 を入力してもそこに留まります。

上記のコードが解決策になるとは思いません。少し遊んだだけです。UpdateSourceTrigger=LostFocusテキストボックスイベントから手動でバインディングを行う必要があると思いますTextChanged...しかし、あなたの問題に対する明確な解決策はありません。

于 2012-04-23T05:53:10.160 に答える
0

基本的に、TextBox にはバグがあり、この方法でバインドされた値を変更すると、TextBox の最初の文字のみが更新されます。たとえば、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");
        }
    }
}

最大値に基づいて TextBox の最大文字数を計算するプロパティを追加したことに注意してください。

いいえ、バインディングを追加するだけです

<DataTemplate>
    <TextBox Width="200" Text="{Binding Col1, UpdateSourceTrigger=PropertyChanged}" MaxLength="{Binding MaxValueWidth}"></TextBox>
</DataTemplate>
于 2012-04-25T12:32:51.540 に答える