WPF 绑定用户控件

发布于 2024-10-14 00:44:24 字数 2370 浏览 3 评论 0原文

好的,我创建了两个东西,一个 MainWindowViewModel 和一个 TabControlViewModel。在我的 TabControlViewModel 中,我的视图基本上是一个带有 3 个 tabitem 的 TabControl(Welcome/tabItem1/tabItem2)。

我的目标是当应用程序启动时,我只看到欢迎选项卡,然后当我选择“文件”->“欢迎”选项卡时,我会看到“欢迎”选项卡。打开两个 tabItems 都变得可见,并且焦点显示我的 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 中?非常感谢大家的耐心等待...:)

Ok, so I've created two things, a MainWindowViewModel and a TabControlViewModel. Within my TabControlViewModel my View is basically a TabControl with 3 tabitems (Welcome/tabItem1/tabItem2).

My goal is when the application starts up I see the welcome tab only and then when I select File -> Open both tabItems become visible and the focus shows my tabItem2 displaying the text file content.

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";
    }

I guess my biggest question is, should my Menu commands be in this TabControlViewModel or in my MainWindowViewModel? Many thanks for your patience here folks...:)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

り繁华旳梦境 2024-10-21 00:44:25

如果您使用 mvvm-light 框架 (http://mvvmlight.codeplex.com/),您可以控制1 双击某个项目时广播一条消息。然后让控制 2 订阅该类型的消息。当它收到消息时,它可以将 Datacontext 设置为正确的值。当然,这假设您正在使用 mvvm,并且每个用户控件都有自己的视图模型。

广播代码可能如下所示:

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);
        }
    }

If you use the mvvm-light framework (http://mvvmlight.codeplex.com/) you could have control 1 broadcast a message when an item is double clicked. Then have control 2 subscribed to messages of that type. When it receives the message, it can set the Datacontext to the correct value. This of course assumes you are using mvvm, and each usercontrol has it's own viewmodel.

The broadcast code might look something like this:

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");
    }
}

To receiver code looks something like this:

    public class myModel
    {
        public myModel()
        {
            Messenger.Default.Register<string>(this, DoSomething);
        }

        public void DoSomething(string item)
        {
            System.Windows.MessageBox.Show(item);
        }
    }
梓梦 2024-10-21 00:44:25

您可以使用 DependencyProperty 一些教程
然后像在默认控件上所做的那样绑定到它。

MyTabControl 的代码(我假设所有选项卡都是在 Xaml 中创建的 InitializeComponent 之后生成的,因此如果您稍后添加任何新的属性,则需要更新属性):

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 上投入一些时间,因为在许多情况下它更容易。

You can create ItemsSource property on your custom control using DependencyProperty some tutorial
and later bind to it just like you are doing on default controls.

Code for your MyTabControl(I'm assuming all tabs are generated just after InitializeComponent - created in Xaml, so if you are addind any new later you need to update property):

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;
    }
}

This code will be working without any problems but at some point it would be worth for you to invest some time in mvvm as in many cases it's just easier.

﹏半生如梦愿梦如真 2024-10-21 00:44:25

我一直在阅读视图模型,但认为我的简单应用程序不需要它。

在这里你几乎肯定是错的。

事实上,如果您使用的是视图模型,那么您在这里尝试做的事情非常简单:您不需要编写控件之间的相互关系,而是构建一个视图模型对象的集合,它是以下对象的 ItemsSource选项卡控件和列表框。

如果您希望双击列表框中的某个项目来执行影响选项卡控件中显示的内容的操作,请在视图模型中实现命令,然后双击该项目来执行该命令。该命令执行后,它会对视图模型进行任何更改,更改的属性会引发其事件,并且选项卡控件中的显示也会更改。

这不仅是您可以为其编写单元测试的东西(这是另一个主题),它还将列表框和选项卡控件相互解耦。例如,您可以决定用其他类型的项目控件(例如 Telerik RadPanelBar)替换选项卡控件,而根本不必更改任何代码。您可以这样做,因为视图模型是视图的逻辑模型,与视图的任何实现细节隔离。

不要害怕视图模型。它们其实并不复杂。必须实现属性更改通知有点烦人,但归根结底,这是为一致、简单、灵活的软件付出的很小的代价。

I've been reading up on view models and don't think it's required for my simple application.

You are almost certainly mistaken here.

In fact, what you're trying to do here is quite simple if you're using a view model: instead of coding up interrelationships between controls, you build a collection of view model objects that's the ItemsSource of both the tab control and the list box.

If you want double-clicking on an item in your list box to do something that affects what's appearing in the tab control, implement a command in the view model and have double-clicking on the item execute the command. The command executes, it makes whatever changes it makes to the view model, the properties that change raise their events, and the display in the tab control changes.

Not only is this something you can write unit tests for (that's another subject), it also decouples the list box and the tab control from each other. You can, for instance, decide to replace the tab control with some other kind of items control (like a Telerik RadPanelBar) and not have to change any code at all. You can do this because the view model is a logical model of the view that's insulated from any of the view's implementation details.

Don't be scared of view models. They're really not complicated. It's a bit annoying to have to implement property-changed notification, but at the end of the day that's a very small price to pay for consistent, simple, flexible software.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文