【问题标题】:WPF Binding User ControlsWPF 绑定用户控件
【发布时间】:2011-01-24 20:17:25
【问题描述】:

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

我的目标是当应用程序启动时,我只看到欢迎选项卡,然后当我选择 File -> Open both 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 中?非常感谢大家的耐心等待......:)

【问题讨论】:

    标签: c# wpf binding tabcontrol


    【解决方案1】:

    如果您使用 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);
            }
        }
    

    【讨论】:

    • 根据我读过的东西,我不确定是否有必要在 MVVM 模型中构建这种类型的应用程序......对于我这样的初学者来说似乎很复杂。非常感谢
    【解决方案2】:

    您可以使用 DependencyProperty some tutorial 在自定义控件上创建 ItemsSource 属性 然后像在默认控件上一样绑定到它。

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

    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 上,因为在许多情况下它更容易。

    【讨论】:

    • 我上周读到了这个(不同的链接)并花了很长时间试图让它工作。如果您能发布一些代码,将非常感激。
    【解决方案3】:

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

    你几乎肯定在这里弄错了。

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

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

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

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

    【讨论】:

    • 好吧,我相信 :) 我最终开始简单并尝试了一些事情。在顶部更新了我的代码,所以我可以澄清一下!非常感谢您的 cmets 和建议...我真的很感激。
    猜你喜欢
    • 2013-06-06
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 2010-12-09
    • 2015-01-23
    • 2019-03-01
    相关资源
    最近更新 更多