9

私の中には、次のxamlようなアイテムを入力するリストビューがあります。

List<DataLayer.Models.Dictionary> dicts = DataLayer.Manager.getDictionaries();

if (dicts != null)
{
    foreach (DataLayer.Models.Dictionary dict in dicts)
    {
         this.itemListView.Items.Add(dict);
    }
}

私のDataLayer.Models.Dictionaryオブジェクトには、 aと。isSelectedとともにプロパティがあります。NameSubName

名前とサブ名はテンプレートで正常に機能しますが、ユーザーがアイテムをクリックしたときにアイテムを選択して更新するにはどうすればよいですか?

ありがとう!

編集:

xamlは次のようになりましたが、アイテムはまだ選択されていません

    <ListView
        x:Name="itemListView"
        TabIndex="1"
        Grid.Row="1"
        Margin="0,60,0,0"
        Padding="0,0,0,0"
        IsSwipeEnabled="False"
        ScrollViewer.VerticalScrollBarVisibility="Hidden"
        SelectionChanged="itemListView_SelectionChanged_1"
        SelectionMode="Multiple"
        FontFamily="Global User Interface">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="IsSelected" Value="{Binding Source=Selected,Mode=TwoWay}"/>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid Margin="6">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <StackPanel Grid.Column="0" Margin="0,0,0,0">
                        <TextBlock Text="{Binding Name}"/>
                        <TextBlock Text="{Binding SubName}" Style="{StaticResource CaptionTextStyle}" TextWrapping="Wrap"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
4

1 に答える 1

8

[編集]この質問は実際にはWPFのタグが付けられていないことに気づきました。しかし、うまくいけば、それはまだ適用されます。

WPFは本質的にMVVMです。コードビハインドでコントロールを直接操作することは、一般的には良い考えではありません。したがって、ViewModelと呼ばれる「見やすい」モデルを作成することをお勧めします。こちらをご覧ください。また、バインディングを使用するには、変化する環境で、プロパティやコレクションの変更を通知して、コントロールを更新できるようにする必要があります。

まず第一に、辞書のコレクションがあるので、変更を通知できるようにこのコレクションを作成します。ObservableCollectionはそれを行うことができます。一般的な経験則として、WPFで使用されるコレクションは、ObservableCollectionを使用するか、それから派生させる必要があります。

だからここに競争の実例があります:

PropertyChangedレイザーを注入するためにFODYを使用していることを念頭に置いてください。手動で行うを参照してください

public class Dict : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name { get; set; }
    public string SubName { get; set; }
    public bool Selected { get; set; }
}

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<Dict> Dictionaries { get; set; }

    public ViewModel()
    {
        Dictionaries = new ObservableCollection<Dict>()
        {
            new Dict()
                {
                    Name = "English",
                    SubName = "en",
                    Selected = false,
                },

                new Dict()
                {
                    Name = "English-British",
                    SubName = "en-uk",
                    Selected = true
                },

                new Dict()
                {
                    Name = "French",
                    SubName = "fr",
                    Selected = true
                }
        };

        Dictionaries.CollectionChanged += DictionariesCollectionChanged;
    }

    private void DictionariesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch(e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach(var dict in e.NewItems.Cast<Dict>())
                    dict.PropertyChanged += DictionaryChanged;
                break;
            case NotifyCollectionChangedAction.Remove:
                foreach (var dict in e.OldItems.Cast<Dict>())
                    dict.PropertyChanged -= DictionaryChanged;
                break;
        }
    }

    private void DictionaryChanged(object sender, PropertyChangedEventArgs e)
    {
        Dict dictionary = (Dict)sender;

        //handle a change in Dictionary
    }
}

これにより、いつでもオブジェクトを追加または削除できますが、ここではコンストラクターでオブジェクトを初期化しています。

次に、これをウィンドウまたはコントロールに配置します。より自己完結型にするために名前空間を含めました。ただし、これはWPF名前空間の場合です。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:WpfApplication1">

    <Window.Resources>
        <local:ViewModel x:Key="viewmodel"/>
    </Window.Resources>

    <ListView
        x:Name="itemListView"
        DataContext="{StaticResource ResourceKey=viewmodel}"
        ItemsSource="{Binding Path=Dictionaries}"
        SelectionMode="Multiple">

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="IsSelected" Value="{Binding Path=Selected, Mode=TwoWay}"/>
            </Style>
        </ListView.ItemContainerStyle>

        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid Margin="6">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <StackPanel Grid.Column="0" Margin="0,0,0,0">
                        <TextBlock Text="{Binding Name}"/>
                        <TextBlock Text="{Binding SubName}" TextWrapping="Wrap"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Window>

コレクションにObservableCollectionを使用せず、WPFが読み込まれた後に要素の追加を開始すると、ListViewを更新する必要があることをバインディングマネージャーに通知することはありません。

上記の起動時:

開始時に、焦点が合っていない

選択したものからの戻り値をオーバーライドすることにより、基になるDictionariesコレクションが変更されていること(つまり、ListViewだけでなく)を簡単に確認できます。

public bool Selected { get { return true; } set {/* do nothing*/ }}

つまり、ビューで選択を解除しようとしても、すべてが常に選択されます。常に次のようになります。

常に選択

スタイリングは別の問題です。フォーカスがない場合、リストは異なって見えます。こちらをご覧ください

これで、選択の変更に対応することはコードビハインドで行うことができますが、それはロジックとビューを混合することになります。

[編集]任意のディクトの変更を検出する機能を含むように更新されました(選択された変更を含む)

あなたはそれを単純化するためにこれを調べることができます

お役に立てれば。

于 2013-03-02T09:50:16.773 に答える