2

OK、ここに奇妙なものがあります。私が理解しようとしているのは、最初のリストビューの選択に基づいて、ObservableCollection によって取り込まれた 1 つのリストビューを作成し、別の ObservableCollection によって取り込まれた別の ListView を更新し、次に valueconverter を使用して、組み合わせた選択に基づいてチェックボックスをオンまたはオフにする方法です。 2 番目のリストビューに現在のアイテムが表示されます。この部分は、マルチバインディングを使用して多少作業していますが、困惑している部分は、2番目のリストビューでアイテムをチェックまたはチェック解除するときに、そのイベントとそのリストビューで現在チェックされているすべてのアイテムを取得できるようにする必要があることです。それに基づくデータベースフィールド。

私はこれがあまり意味をなさないかもしれないことを知っています. セカンドリストビューのチェックボックスをオンまたはオフにすると、コンバーターが ConvertBack メソッドを実行しようとして失敗することがわかりますが、単に null を返すように設定すると、コードは失敗しなくなりますが、チェックボックスは強調表示されます検証エラーが発生したように赤で。

マルチバインディングがここに行く方法であるかどうかさえわかりません.Josh Smithのマルチセレクションリストビューのものを見てきましたが、必要な変換では、それをうまく実装する方法もわかりません.

誰かが何かアイデアを持っているなら、私はそれを大いに感謝します. また、私の必要性を明確に説明しなかった場合は申し訳ありませんが、混沌とした説明とコードで、私がどこに向かっているのかを確認できることを願っています.

前もって感謝します!

2 番目の ListView にフィードする最初の ListView

<Grid>
                <ListView x:Name="listRule" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3,3,3,3" ItemsSource="{Binding RuleListing}" exts:Selected.Command="{Binding RuleSelectedCommand}" SelectedIndex="0">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding Path=DisplayName}" ToolTip="{Binding Path=Expression}" FontWeight="Bold"/>
                                <TextBlock Text=" ( "/>
                                <TextBlock Text="{Binding Description}" FontStyle="Italic" />
                                <TextBlock Text=" )"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Grid>

コンバーターとマルチバインディングを使用した 2 番目の ListView

<Grid HorizontalAlignment="Stretch">
                <Grid.Resources>
                    <converters:RuleToRoleBooleanConverter x:Key='RuleRoleConverter' />                        
                    <DataTemplate x:Key="RoleTemplate">
                        <Grid HorizontalAlignment="Stretch">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*" MinWidth="200"/>
                                <ColumnDefinition Width="20"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding RoleName}" HorizontalAlignment="Left" Margin="3,0,0,0" Grid.Column="0" />
                            <CheckBox HorizontalAlignment="Right" Margin="0,0,3,0" Grid.Column="1">
                                <CheckBox.IsChecked>
                                    <MultiBinding Converter="{StaticResource RuleRoleConverter}">
                                        <Binding ElementName="listRule" Path="SelectedItem" />
                                        <Binding Path="RoleName"/>
                                    </MultiBinding>
                                </CheckBox.IsChecked>
                            </CheckBox>
                        </Grid>
                    </DataTemplate>
                </Grid.Resources>
                <ListView Name="listRoles" ItemsSource="{Binding RoleListing}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                          SelectionMode="Multiple" ItemTemplate="{StaticResource ResourceKey=RoleTemplate}">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="{x:Type ListBoxItem}">
                            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsRoleSelected}"/>
                        </Style>
                    </ListView.ItemContainerStyle>
                </ListView>
            </Grid>

値コンバーター

public class RuleToRoleBooleanConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values[0] != null && values[1] != null)
        {
            string expression = ((EliteExtenderRule)values[0]).Expression;
            string role = values[1].ToString();

            if (expression.Contains("R:*") || expression.Contains("R:" + role))
            {
                return true;
            }
        }
        return false;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;// new object[] { (bool)value, null };
    }}
4

1 に答える 1

0

問題の最初の部分の解決策があるかもしれません。つまり、「最初のリストビューの選択に基づいて、ObservableCollectionによって入力された1つのリストビューを作成し、別のObservableCollectionによって入力された別のListViewを更新する方法を理解することです」。

しかし、前に、問題のこの部分では、ソース ListView の選択された項目プロパティにターゲット ListView をバインドするだけでニーズを満たすことができますか?

     <ListView x:Name="listOne" Grid.Column="0" Width="50" Height="200" ItemsSource="{Binding SourceList}" SelectionMode="Extended"  />
    <ListView x:Name="listTwo" Grid.Column="1" Width="50" Height="200" ItemsSource="{Binding ElementName=listOne, Path=SelectedItems}" />

そうでない場合は、最近のプロジェクトで同様の問題が発生し、ソース リストに適用される動作を思いつきました。

ビューの DataContext としてそのようなビュー モデルがあるとします。

    public ObservableCollection<BusinessAdapter> SourceList { get; private set; }
    public ObservableCollection<BusinessAdapter> TargetList { get; private set; }
    public Window1()
    {
        InitializeComponent();
        DataContext = this;
        SourceList = new ObservableCollection<BusinessAdapter>();
        TargetList = new ObservableCollection<BusinessAdapter>();

        for (int i = 0; i < 50; i++)
        {
            SourceList.Add(new BusinessAdapter { BusinessProperty = "blabla_" + i });
        }
    }

そして、あなたの見解では、次のようなものがあります:

    <ListView x:Name="listOne" Grid.Column="0" Width="50" Height="200" ItemsSource="{Binding SourceList}" SelectionMode="Extended" />
    <ListView x:Name="listTwo" Grid.Column="1" Width="50" Height="200" ItemsSource="{Binding TargetList}" />

次に、この動作をソース リスト ボックスにアタッチし、ターゲット ビュー モデル ソースをそれに渡すことができます。

==> 動作:

public class ListBoxMultiSelectionBehavior
{
    public static IList<BusinessAdapter> GetTargetList(DependencyObject obj)
    {
        return (IList<BusinessAdapter>)obj.GetValue(TargetListProperty);
    }

    public static void SetTargetList(DependencyObject obj, IEnumerable<BusinessAdapter> value)
    {
        obj.SetValue(TargetListProperty, value);
    }

    // Using a DependencyProperty as the backing store for Adapter.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TargetListProperty =
        DependencyProperty.RegisterAttached("TargetList", typeof(IList<BusinessAdapter>), typeof(ListBoxMultiSelectionBehavior), new UIPropertyMetadata(null, OnListChanged));

    /// <summary>
    /// Model List changed callback
    /// </summary>
    /// <param name="d"></param>
    /// <param name="e"></param>
    private static void OnListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var mSelector = d as ListView ;

        if (mSelector != null)
        {
            mSelector.SelectionChanged -= MSelectorSelectionChanged;

            //Multiple or Extented selection mode are mandatory
            if (mSelector.SelectionMode == SelectionMode.Single)
            {
                return;
            }
            mSelector.SelectedItems.Clear();

            //"binding" => model to view
            //get the model's list
            var a = GetTargetList(d);
            if (a != null)
            {
                //for each model in the list
                foreach (var ba in a)
                {
                    //in the listbox items collection
                    foreach (var item in mSelector.Items)
                    {
                        //find the correspondance and if found
                        if (((BusinessAdapter)item).BusinessProperty == ba.BusinessProperty)
                        {
                            //add item to selected items
                            mSelector.SelectedItems.Add(item);

                        }
                    }

                }
            }

            //"binding" => view to model
            //subscribe to changes in selection  in the listbox
            mSelector.SelectionChanged += MSelectorSelectionChanged;
        }
    }



    static void MSelectorSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e != null)
        {
            var adapter = GetTargetList(sender as DependencyObject);
            var list = adapter;//copy

            if (e.RemovedItems.Count > 0 /*&& e.RemovedItems.Count != list.Count*/)
            {
                foreach (var ba in e.RemovedItems.Cast<BusinessAdapter>())
                {
                    list.Remove(ba);
                }
            }
            if (e.AddedItems.Count > 0)
            {
                foreach (var ba in e.AddedItems.Cast<BusinessAdapter>())
                {
                    list.Add(ba);
                }

            }
        }

    }
}

基本的には、初期化時にターゲット リスト アイテムを取得してソース リストに入力し (一方の方法)、リスト ボックスのソース選択変更イベントをサブスクライブしてターゲット リストに入力します (もう一方の方法)。次に、アイテムが動作に追加されると、ターゲットリストボックスのジェストが更新されます。

新しい XAML は次のようになります。

    <ListView x:Name="listOne" Grid.Column="0" Width="50" Height="200" ItemsSource="{Binding SourceList}"  SelectionMode="Extended" StackOverflow:ListBoxMultiSelectionBehavior.TargetList="{Binding TargetList}" />
    <ListView x:Name="listTwo" Grid.Column="1" Width="50" Height="200" ItemsSource="{Binding TargetList}" />

あなたの問題の 2 番目の部分については、今のところ思い浮かびません... ごめんなさい :/

于 2011-04-11T11:41:29.443 に答える