2

好的我在這裏有一個奇怪的。我想弄清楚的是,如何讓一個ListView由ObservableCollection填充,根據第一個listview的選擇更新另一個由另一個ObservableCollection填充的ListView,然後使用valueconverter根據選擇組合來選中或取消選中複選框與第二個列表視圖中的當前項目。這部分我有點使用多重綁定工作,但有我難倒的部分是當我檢查或取消選中第二個列表視圖中的項目時,我需要能夠抓取該事件,並且該列表中的所有當前選中的項目都會查看更新數據庫字段基於此。Multibinding Multiselection ListView

我知道這可能沒有多大意義,我正在努力如何使它更清晰,但下面是xaml的兩個listviews和轉換器的代碼。我可以看到,當我在secodn listview中選中或取消選中一個框時,轉換器會嘗試執行ConvertBack方法,但如果將其設置爲僅返回null,則代碼不再起作用,但複選框將突出顯示紅色像驗證錯誤已經發生。

我甚至不確定多重綁定是如何去這裏的,我已經看過Josh Smith的多選列表視圖的東西,但是隨着所需的轉換,我無法看到如何成功實現它。

如果有人有任何想法,我將不勝感激。如果我沒有非常清楚地解釋我的需求,我也很抱歉,但我希望能夠看到混亂的描述和代碼,以便我能夠看到我的目標。

在此先感謝!

首先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> 

二ListView和multibinding

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

回答

0

我可能有問題的第一部分的解決方案,即「要弄清楚如何有一個列表視圖,由ObservableCollection填充,更新另一個ListView,由另一個ObservableCollection填充,基於第一個列表視圖的選擇」。

但之前,對於這部分問題,dit只是將目標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); 
       } 

      } 
     } 

    } 
} 

它的作用主要是初始化時,他retreive目標列表項和填充源列表(單程),並訂閱列表框中源選擇變事件來填充目標列表(另一種方式)。然後,在項目添加到行爲中時更新目標列表框的動作。

新的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}" /> 

對於你的問題的第二部分,我沒有的東西,我的腦海裏來,現在...對不起:/