不使用 Messenger 或 EventAggregator 的 ItemsControl 中的 Items 之间的通信
Communication between Items in ItemsControl without using Messenger or EventAggregator
在不使用 Messenger 或 EventAggregator 的情况下,ItemsControl 中的 Bindings 中的 Items 如何相互通信。下面是一个简化但完整的案例。我在 ItemsControl 中有两个关联的项目。 UpdateTheSecondItemFromTheFirstItem() 可以通过使用 prism 中的 EventAggregator(messenger) 来完成。但我想知道是否有更直接的解决方案可以在不使用 Messenger 的情况下实现这一目标。
主窗口:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ItemsControl ItemsSource="{Binding MyItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="MyType">
<Grid>
<Slider Value="{Binding MyNum}" Minimum="0" Maximum="100"></Slider>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
我的类型
using Prism.Mvvm;
namespace WpfApp2
{
public class MyType : BindableBase
{
private bool _isFirstItem=false;
private int _myVar;
public int MyVar
{
get { return _myVar; }
set
{
if (Equals(_myVar, value)) return;
SetProperty(ref _myVar, value);
}
}
public MyType(bool isFirst)
{
_isFirstItem = isFirst;
MyVar = 0;
}
}
}
MainWindowViewModel
using Prism.Mvvm;
using System.Collections.ObjectModel;
namespace WpfApp2
{
public class MainWindowViewModel:BindableBase
{
private ObservableCollection<MyType> _myItems = new ObservableCollection<MyType>();
public ObservableCollection<MyType> MyItems
{
get { return _myItems; }
set
{
if (Equals(_myItems, value)) return;
SetProperty(ref _myItems, value);
if(_isFirstItem) UpdateTheSecondItemFromTheFirstItem();
}
}
private void UpdateTheSecondItemFromTheFirstItem(){
}
public MainWindowViewModel()
{
MyType[] MyTypeArr =
{
new MyType(true),
new MyType(false)
};
MyItems.AddRange(MyTypeArr);
}
}
}
找到解决方案,只需要使用 ref,这与 C++ 中的指针完全一样:
MainWindowViewModel:
public MainWindowViewModel()
{
MyType Type1 = new MyType();
MyType Type2 = new MyType();
MyItems.Add(Type1);
MyItems.Add(Type2);
Type1.SetPair(ref Type2);
}
MyType.cs:
using Prism.Mvvm;
namespace WpfApp2
{
public class MyType : BindableBase
{
private int _myVar;
public int MyVar
{
get { return _myVar; }
set
{
if (Equals(_myVar, value)) return;
SetProperty(ref _myVar, value);
if (MyPair!=null)
{
MyPair.MyVar = value;
}
}
}
public MyType()
{
MyVar = 0;
}
MyType MyPair { get; set; }
public void SetPair(ref MyType pair)
{
MyPair = pair;
}
public MyType GetPair()
{
return MyPair;
}
}
}
现在,拖动滑块时,第二个滑块会随着第一个滑块移动。
在不使用 Messenger 或 EventAggregator 的情况下,ItemsControl 中的 Bindings 中的 Items 如何相互通信。下面是一个简化但完整的案例。我在 ItemsControl 中有两个关联的项目。 UpdateTheSecondItemFromTheFirstItem() 可以通过使用 prism 中的 EventAggregator(messenger) 来完成。但我想知道是否有更直接的解决方案可以在不使用 Messenger 的情况下实现这一目标。 主窗口:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ItemsControl ItemsSource="{Binding MyItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="MyType">
<Grid>
<Slider Value="{Binding MyNum}" Minimum="0" Maximum="100"></Slider>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
我的类型
using Prism.Mvvm;
namespace WpfApp2
{
public class MyType : BindableBase
{
private bool _isFirstItem=false;
private int _myVar;
public int MyVar
{
get { return _myVar; }
set
{
if (Equals(_myVar, value)) return;
SetProperty(ref _myVar, value);
}
}
public MyType(bool isFirst)
{
_isFirstItem = isFirst;
MyVar = 0;
}
}
}
MainWindowViewModel
using Prism.Mvvm;
using System.Collections.ObjectModel;
namespace WpfApp2
{
public class MainWindowViewModel:BindableBase
{
private ObservableCollection<MyType> _myItems = new ObservableCollection<MyType>();
public ObservableCollection<MyType> MyItems
{
get { return _myItems; }
set
{
if (Equals(_myItems, value)) return;
SetProperty(ref _myItems, value);
if(_isFirstItem) UpdateTheSecondItemFromTheFirstItem();
}
}
private void UpdateTheSecondItemFromTheFirstItem(){
}
public MainWindowViewModel()
{
MyType[] MyTypeArr =
{
new MyType(true),
new MyType(false)
};
MyItems.AddRange(MyTypeArr);
}
}
}
找到解决方案,只需要使用 ref,这与 C++ 中的指针完全一样:
MainWindowViewModel:
public MainWindowViewModel()
{
MyType Type1 = new MyType();
MyType Type2 = new MyType();
MyItems.Add(Type1);
MyItems.Add(Type2);
Type1.SetPair(ref Type2);
}
MyType.cs:
using Prism.Mvvm;
namespace WpfApp2
{
public class MyType : BindableBase
{
private int _myVar;
public int MyVar
{
get { return _myVar; }
set
{
if (Equals(_myVar, value)) return;
SetProperty(ref _myVar, value);
if (MyPair!=null)
{
MyPair.MyVar = value;
}
}
}
public MyType()
{
MyVar = 0;
}
MyType MyPair { get; set; }
public void SetPair(ref MyType pair)
{
MyPair = pair;
}
public MyType GetPair()
{
return MyPair;
}
}
}
现在,拖动滑块时,第二个滑块会随着第一个滑块移动。