我的视图中有一个简单的ListView:
<ListView x:Name="ObjectListView" HorizontalAlignment="Left" Height="105" Margin="253,268,0,0" VerticalAlignment="Top" Width="163" SelectionChanged="ObjectListView_SelectionChanged">
<TextBox Width="100"/>
<Button Width="100" Content="Test"/>
<Label Width="100" Content="Label"/>
</ListView>
在我的ViewModel中,我有一个ObservableCollection,它做了一些(对于这个问题无关紧要)的事情:
public ObservableCollection<Object> ObjectCollection
{
get { return _conversionCollection; }
set
{
if (_conversionCollection != value)
{
_conversionCollection = value;
RaisePropertyChanged("ObjectList");
}
}
}
最终,这些对象自然落在模型中(编辑:通过RaisePropertyChanged和一些函数的帮助),但我的问题是View和ViewModel之间的连接。
目前,我已经解决了这个问题(在View的代码隐藏中):
public MainWindow()
{
InitializeComponent();
_viewModel = (RibbonViewModel)base.DataContext;
}
private void ObjectListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_viewModel.ObjectCollection.Clear();
foreach(Object item in ObjectListView.SelectedItems)
{
_viewModel.ObjectCollection.Add(item);
}
}
这并不是太美丽,所以我想要做得恰到好处。
答案 0 :(得分:2)
您只需要将ListView
SelectedItems
绑定到ObservableCollection
,这样您的收藏就会使用绑定自动更新。实际上,您不需要将事件添加到您的代码中。
<ListView x:Name="ObjectListView" HorizontalAlignment="Left" Height="105" Margin="253,268,0,0" VerticalAlignment="Top" Width="163" SelectedItems="{Binding Path=ObjectCollection}">
<TextBox Width="100"/>
<Button Width="100" Content="Test"/>
<Label Width="100" Content="Label"/>
</ListView>
要实现您想要的效果,请尝试使用Interaction triggers
,如下所示
将以下xmlns添加到您的xaml
xmlns:i="http://schemas.microsoft.com/expression//2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
不要忘记添加该引用:
Microsoft.Expression.Interactions System.Windows.Interactivity
<ListView x:Name="ObjectListView" HorizontalAlignment="Left" Height="105" Margin="253,268,0,0" VerticalAlignment="Top" Width="163">
<TextBox Width="100"/>
<Button Width="100" Content="Test"/>
<Label Width="100" Content="Label"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedItems" Value="{Binding Path=SelectedItems, ElementName=ObjectListView}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
public System.Collections.IList SelectedItems {
get {
return ObjectCollection;
}
set {
ObjectCollection.Clear();
foreach (var model in value) {
ObjectCollection.Add(model);
}
}
}
答案 1 :(得分:1)
基本上,您需要数据绑定 ViewModel.ObjectCollection
到ListView.SelectedItems
。
默认情况下,WPF控件不支持此功能,但您可以扩展控件以支持此功能。扩展控制的一种方法是行为。有两种类型的行为:
作为附加属性实现的行为。
<ListView my:ListViewExtension.SelectedItems="{Binding ObjectCollection}" />
我决定使用秒。基本上你创建自定义附加属性,在DependencyPropertyChanged回调中,你可以通过附加到元素'eventhandlers来“注入”任何代码到框架元素。
public static class ListViewExtentions
{
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
"SelectedItems", typeof (IList), typeof (ListViewExtentions), new PropertyMetadata(SelectedItems_PropertyChanged));
public static void SetSelectedItems(DependencyObject element, IList value)
{
element.SetValue(SelectedItemsProperty, value);
}
public static IList GetSelectedItems(DependencyObject element)
{
return (IList)element.GetValue(SelectedItemsProperty);
}
private static void SelectedItems_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var listView = (ListView) d;
SynchronizeCollections(listView.SelectedItems, (IList)e.NewValue);
listView.SelectionChanged += (sender, args) =>
{
var listviewSelectedItems = ((ListView) sender).SelectedItems;
var viewmodelCollection = GetSelectedItems((ListView) sender);
SynchronizeCollections(listviewSelectedItems, viewmodelCollection);
};
}
private static void SynchronizeCollections(IList source, IList target)
{
var oldItems = target.OfType<object>().Except(source.OfType<object>()).ToArray();
var newItems = source.OfType<object>().Except(target.OfType<object>()).ToArray();
foreach (var oldItem in oldItems) target.Remove(oldItem);
foreach (var newItem in newItems) target.Add(newItem);
}
}
您可以使用propa
代码段生成附加属性
提示:我建议您将ViewModel.ObjectCollection
重命名为ViewModel.SelectedItems
,因为现在它具有误导性。
答案 2 :(得分:0)
也许这个例子可以帮到你。
<Grid>
<ListView HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding ObjectCollection}" SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Width="100" Grid.Column="0" Text="{Binding Text}"/>
<Button Width="100" Content="Test" Grid.Column="1"/>
<Label Width="100" Grid.Column="2" Content="{Binding Label}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
代码:
namespace WpfApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class Obj : INotifyPropertyChanged
{
public string Text { get; set; }
private string label;
public string Label
{
get
{
return this.label;
}
set
{
this.label = value;
this.RaisePropertyChaged("Label");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChaged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
public class ViewModel
{
private Obj selectedItem;
public Obj SelectedItem
{
get
{
return this.selectedItem;
}
set
{
this.selectedItem = value;
this.selectedItem.Label = value.Text;
}
}
public ObservableCollection<Obj> ObjectCollection { get; set; }
public ViewModel()
{
ObjectCollection = new ObservableCollection<Obj>();
ObjectCollection.Add(new Obj { Text = "First" });
ObjectCollection.Add(new Obj { Text = "Second" });
ObjectCollection.Add(new Obj { Text = "Third" });
}
}
}
答案 3 :(得分:-1)
<ListView x:Name="Lst" SelectedItem="{Binding ChosenItem}"> ... </ListView>
这将在ChosenItem DP
中添加所选项目,在其设置器中,您只需将项目添加到集合中即可。
private static void ChosenItemPropertyCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
controls.Add(e.NewValue.ToString());
}