[英]WPF Binding User Controls
好的,所以我创建了两件事,一个MainWindowViewModel和一个TabControlViewModel。 在我的TabControlViewModel中,我的视图基本上是一个带有3个Tabitem(Welcome / tabItem1 / tabItem2)的TabControl。
我的目标是当应用程序启动时,我只会看到“欢迎”选项卡,然后在选择“文件”->“打开”时,两个tabItem都可见,并且焦点显示我的tabItem2显示文本文件内容。
MainWindow.Xaml
<Menu DockPanel.Dock="Top" Width="Auto" Height="25" Name="Menu1">
<MenuItem Header="_File" VerticalContentAlignment="Top" >
<MenuItem Header="_New" Command="{Binding NewCommand}" />
<MenuItem Header="_Open" Command="{Binding OpenCommand}">
TabControlViewModel.cs
class TabControlViewModel : TabContainer
{
private DelegateCommand openCommand;
public ICommand OpenCommand
{
get
{
if (openCommand == null)
openCommand = new DelegateCommand(Open);
return openCommand;
}
}
private void Open(object obj)
{
ProcessOpenCommand();
}
private void ProcessOpenCommand()
{
if (dataChanged)
{
SaveFirst();
ShowOpenDialog();
}
else
{
ShowOpenDialog();
}
}
private void ShowOpenDialog()
{
System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
ofd.Filter = "Text File (*.txt)|*.txt";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
filePath = ofd.FileName;
ReadFile(filePath);
SetTitle(ofd.SafeFileName);
RuleTab.Focus();
}
}
private string SaveFirst()
{
MessageBoxResult mbr = System.Windows.MessageBox.Show("Do you want to save changes?", "Save Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
if (mbr == MessageBoxResult.Yes)
{
if (filePath != null)
{
SaveFile(filePath);
}
else
{
ProcessSaveCommand();
}
}
else if (mbr == MessageBoxResult.Cancel)
{
return "Cancel";
}
return "Nothing";
}
我想我最大的问题是,我的菜单命令应该在此TabControlViewModel中还是在MainWindowViewModel中? 非常感谢您在这里的耐心等候... :)
您可以在DependencyProperty上使用某些教程在自定义控件上创建ItemsSource属性,然后像在默认控件上一样将其绑定到该控件上。
MyTabControl的代码(我假设所有选项卡都是在InitializeComponent之后生成的-在Xaml中创建,因此如果稍后添加addind,则需要更新属性):
public partial class MyTabControl
{
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register(
"Items",
typeof(IEnumerable),
typeof(MyTabControl),
null);
public IEnumerable Items
{
get { return (IEnumerable)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public MyTabControl()
{
InitializeComponent();
Items = tabControl.Items;
}
}
这段代码可以正常工作,但是在某些时候,值得在mvvm上花一些时间,因为在许多情况下,这很容易。
如果您使用mvvm-light框架( http://mvvmlight.codeplex.com/ ),则可以在双击项目时使控件1广播一条消息。 然后让控件2订阅该类型的消息。 收到消息后,可以将Datacontext设置为正确的值。 当然,这假定您正在使用mvvm,并且每个usercontrol都有其自己的viewmodel。
广播代码可能看起来像这样:
public class MainViewModel
{
public RelayCommand myCommand { get; private set; }
public MainViewModel()
{
myCommand = new RelayCommand( () => SendTheMessage());
}
public void SendTheMessage()
{
Messenger.Default.Send("I have sent the message");
}
}
接收者代码如下所示:
public class myModel
{
public myModel()
{
Messenger.Default.Register<string>(this, DoSomething);
}
public void DoSomething(string item)
{
System.Windows.MessageBox.Show(item);
}
}
我一直在阅读视图模型,并且认为我的简单应用程序不需要它。
您几乎可以肯定在这里弄错了。
实际上,如果您使用的是视图模型,那么您想要做的事情很简单:您无需构建控件之间的相互关系,而是构建视图模型对象的集合,该对象既是选项卡控件又是列表的ItemsSource
框。
如果要双击列表框中的某个项目来执行某些操作,这些操作会影响选项卡控件中显示的内容,请在视图模型中实现一个命令,然后双击该项目执行该命令。 该命令将执行,对视图模型进行任何更改,更改的属性将引发事件,并且选项卡控件中的显示也会更改。
您不仅可以为此编写单元测试(这是另一个主题),还可以使列表框和选项卡控件彼此分离。 例如,您可以决定用其他类型的项目控件(例如Telerik RadPanelBar
)替换tab控件,而根本不必更改任何代码。 您可以执行此操作,因为视图模型是视图的逻辑模型,并且与任何视图的实现详细信息隔离开来。
不要害怕视图模型。 它们确实并不复杂。 必须实施属性更改通知有点烦人,但最终,购买一致,简单,灵活的软件要付出很小的代价。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.