1

リストボックスにはチェックボックスのある項目があり、TextBlock には現在チェックされている項目の数を示すカウンターを更新したいと考えています。単純なシナリオですが、カウンターのバインディングを更新する際に問題があります。

私のxaml:

<Window x:Class="ListboxWithCounting.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:ListboxWithCounting"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MyViewModel />
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate x:Key="CheckBoxListItem">
            <Border x:Name="CheckBoxItemElement" 
                    Background="Transparent" 
                    Padding="0,2,0,2">
                <CheckBox Content="{Binding Name}" 
                          IsChecked="{Binding Path=IsChecked,Mode=TwoWay,
                    UpdateSourceTrigger=PropertyChanged}"/>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBlock Grid.Column="1">
            <TextBlock.Text>
                <MultiBinding StringFormat="Items checked: {0} of {1}">
                    <Binding Path="ColumnsChecked" />
                    <Binding Path="ColumnsCount" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>

        <ListBox ItemTemplate="{StaticResource CheckBoxListItem}" 
                         x:Name="Columns" 
                         ItemsSource="{Binding Columns}" />
    </Grid>
</Window>

私のビューモデルと単一のアイテム:

public class Item : INotifyPropertyChanged
    {
        public string Name { set; get; }

        private bool isChecked;
        public bool IsChecked
        {
            get
            {
                return isChecked;
            }
            set
            {
                isChecked = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }

    public class MyViewModel
    {
        public int ColumnsCount
        {
            get
            {
                return Columns.Count;
            }
        }

        public int ColumnsChecked
        {
            get
            {
                return Columns.Where(x => x.IsChecked).Count();
            }
        }

        public List<Item> Columns
        {
            get
            {
                var data = new List<Item>()
                {
                    new Item(){ Name = "Item1", IsChecked=true },
                    new Item(){ Name = "Item2" },
                    new Item(){ Name = "Item3" }
                };

                data.ForEach(x => x.PropertyChanged += (s, e) => { });

                return data;
            }
        }
    }

リストの状態のすべてのチェックボックスが変更されたときにマルチバインディングをトリガーするにはどうすればよいですか?

[アップデート]

スラッグスターのおかげで、作業コード:

public class Item : INotifyPropertyChanged
    {
        public string Name { set; get; }

        private bool isChecked;
        public bool IsChecked
        {
            get
            {
                return isChecked;
            }
            set
            {
                if (isChecked != value)
                {
                    isChecked = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }

    public class MyViewModel : INotifyPropertyChanged
    {
        public int ColumnsCount
        {
            get
            {
                return Columns.Count;
            }
        }

        public int ColumnsChecked
        {
            get
            {
                return Columns.Where(x => x.IsChecked).Count();
            }
        }

        private List<Item> columns;
        public List<Item> Columns
        {
            get
            {
                if (columns == null)
                {
                    columns = new List<Item>()
                    {
                        new Item(){ Name = "Item1", IsChecked=true },
                        new Item(){ Name = "Item2" },
                        new Item(){ Name = "Item3" }
                    };
                }

                columns.ForEach(x =>
                {
                    x.PropertyChanged -= x_PropertyChanged;
                    x.PropertyChanged += x_PropertyChanged;
                });

                return columns;
            }
        }

        void x_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("ColumnsChecked"));
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }
4

1 に答える 1

2

ビューモデルも実装INotifyPropertyChangedして、バインディングがリスト項目のプロパティの変更を認識できるようにする必要があります。

正直なところ、1 つのプロパティだけを通知することでマルチバインディング全体が評価されるかどうかは、はっきりとはわかりません (いずれにせよ、すぐにわかります)。他のバインディングの場合。

public class MyViewModel : INotifyPropertyChanged
{

    [...snip...]

    public List<Item> Columns
    {
        get
        {
            var data = new List<Item>()
            {
                new Item(){ Name = "Item1", IsChecked=true },
                new Item(){ Name = "Item2" },
                new Item(){ Name = "Item3" }
            };

            data.ForEach(x => x.PropertyChanged += (s, e) => {       
                                                                OnPropertyChanged("ColumnsCount");
                                                                OnPropertyChanged("ColumnsChecked");
                                                             });

            return data;
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

}
于 2013-10-07T07:42:39.143 に答える