我知道这可能没有多大意义,我正在努力使它更清晰,但下面是两个列表视图的xaml和转换器的代码。我可以看到,当我在secodn列表视图中选中或取消选中一个框时,转换器会尝试执行转换的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
<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 :(得分:0)
我可能有一个问题的第一部分的解决方案,即“弄清楚如何有一个列表视图,由ObservableCollection填充,更新另一个ListView,由另一个ObservableCollection填充,基于第一个listview的选择”。
但之前,对于这部分问题,dit只是将目标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}" />
然后,您可以在源列表框中附加此行为,并将目标视图模型源传递给它。
==&GT;行为:
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}" />
对于你问题的第二部分,我现在没有想到的东西......对不起:/