我是WPF的新手,现在我遇到的情况是我无法找到任何有效的解决方案。 在我的项目中,我有很多viewmodels和usercontrols。主窗口分为两个,在左侧,我根据当前的视图模型显示用户控件,每个工作正常。当我想根据左侧选择的用户在右侧显示第二个用户控件时,问题就开始了。用户控件有许多文本框和组合框。我将如何从cosequtive视图模型中绑定这些数据?
//mainwindow.xaml
<Window.resources>
<Datatemplate Datatype={x:Type vm:Viewmodel1}>
<loc:Usercontrol1/> // in the left hand side
</DataTemplate>
<Datatemplate Datatype={x:Type vm:Viewmodel2}>
<loc:Usercontrol2/> // in the lefthand side
</DataTemplate>
</Window.Resources>
...
<Grid Grid.Column="0">
<ContentControl Content={Binding CurrentViewModel}/>
</Grid>
<Grid Grid.Column="1">
<Grid.Resources>
<Datatemplate Datatype={x:Type vm:Viewmodel1}>
<loc:Usercontrol3 NameDp={Binding Name}/> // in the right hand side
</DataTemplate>
<Datatemplate Datatype={x:Type vm:Viewmodel2}>
<loc:Usercontrol3/> // in the rightthand side
</DataTemplate>
</Grid.Resources>
</Grid>
// Usercontrol3.xaml
<Grid>
<TextBox Text="{Binding Path=NameDp, ElementName=UserControl3}" />
</Grid>
// UserControl3.cs
public static readonly DependencyProperty NameUCProperty =DependencyProperty.Register("NameDp", typeof(string), typeof(UserControl3), new FrameworkPropertyMetadata(NamePropertyChanged));
public string NameDp
{
get
{
return (string)GetValue(NameUCProperty);
}
set
{
SetValue(NameUCProperty, value);
}
}
//ViewModel
Public Name {get;set;}
在每个视图模型中,我从数据库中获取数据,我想根据用户选择将这些数据绑定到右侧的Usercontrols。我如何绑定这些数据? 这是正确的approch还是我完全错了?
答案 0 :(得分:1)
这绝对是一种方法。对我来说,我会用这种方式组织。我在这里有一个原型,演示了这些东西是如何工作的......
首先,我们的MainWindow
<Window x:Class="WpfUserControlsBindingListeningNotMuchHere.MainWindow"
xmlns:t="clr-namespace:WpfUserControlsBindingListeningNotMuchHere"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:ms="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<Window.DataContext>
<t:ViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<t:UserControl1 x:Name="uc1"
Items="{Binding Items}"
Selected="{Binding Selected, Mode=TwoWay}" />
<t:UserControl2 Grid.Column="1"
DataContext="{Binding Result}" />
</Grid>
</Window>
注意 uc1 。它接收一个列表并公开所选项目。这些都绑定到ViewModel。属性Items
和Selected
是我在UserControl上定义的 DependencyProperties 。如果你愿意,我可以显示代码,但没有它应该是可以理解的。 (如果我调整了DP定义,Mode=TwoWay
可以省去。)
在ViewModel中,我会听取Selected
的更改,并相应地开展工作。
class ViewModel : INotifyPropertyChanged
{
private object _selected;
private object _result;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<object> Items { get; private set; }
public object Selected
{
get { return this._selected; }
set
{
if (_selected == value)
return;
this._selected = value;
PropertyChanged(this, new PropertyChangedEventArgs("Selected"));
}
}
public object Result
{
get { return this._result; }
set
{
if (_result == value )
return;
this._result = value;
PropertyChanged(this, new PropertyChangedEventArgs("Result"));
}
}
public ViewModel()
{
Items = new ObservableCollection<object>();
Items.Add(1);
Items.Add("hello");
Items.Add(3.0d);
PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "Selected")
return;
//DO MASSIVE WORK HER ON BACKGROUND THREAD OR SOMETHING LOL
Result = "OMG THIS TOOK A LONG TIME, " + Selected.ToString();
}
}
所以,我只是在观察对Selected的更改,此时我会完成我的工作(业务逻辑)并在另一个属性中公开结果。然后将其绑定到UI中的第二个UserControl。
正如我所说,UC代码是微不足道的......
<UserControl x:Class="WpfUserControlsBindingListeningNotMuchHere.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="root">
<ListBox ItemsSource="{Binding Items, ElementName=root}"
SelectedItem="{Binding Selected, ElementName=root}" />
</UserControl>
和代码隐藏(OMG CODEBEHIND LOOK OUT EVIL)
public partial class UserControl1 : UserControl
{
#region Items
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register(
"Items",
typeof(IEnumerable<object>),
typeof(UserControl1),
new UIPropertyMetadata(null));
public IEnumerable<object> Items
{
get { return (IEnumerable<object>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
#endregion
#region Selected
public static readonly DependencyProperty SelectedProperty =
DependencyProperty.Register(
"Selected",
typeof(object),
typeof(UserControl1),
new UIPropertyMetadata(null));
public object Selected
{
get { return (object)GetValue(SelectedProperty); }
set { SetValue(SelectedProperty, value); }
}
#endregion
public UserControl1()
{
InitializeComponent();
}
}
和
<UserControl x:Class="WpfUserControlsBindingListeningNotMuchHere.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<TextBlock Text="{Binding}" />
</UserControl>
这个没有代码隐藏。