【问题标题】:Copying a TabItem with an MVVM structure使用 MVVM 结构复制 TabItem
【发布时间】:2013-09-10 01:17:37
【问题描述】:

这是对this question 的扩展尝试。在我的 WPF 程序中,我一直在通过在名为 TrycloneElement 的函数中使用 XamlWriter 来克隆 tabItems。我最初找到了这个函数here,但是这个函数也可以在我上一个问题的链接中查看。

现在我开始担心程序内部的功能,我发现TrycloneElement 函数不会复制分配给它正在克隆的tabItem 的任何代码隐藏功能。

由于 High Core 的链接和对我之前问题的评论,我决定开始通过我的 ViewModel 的数据绑定在我的 tabItems 上实现功能。

这是我实现的命令示例:

public viewModel()
{
    allowReversing = new Command(allowReversing_Operations);
}

public Command AllowReversing
{
       get { return allowReversing; }
} 

private Command allowReversing; 

private void allowReversing_Operations()
{
       //Query for Window1
       var mainWindow = Application.Current.Windows
           .Cast<Window1>()
           .FirstOrDefault(window => window is Window1) as Window1;

       if (mainWindow.checkBox1.IsChecked == true) //Checked
       {
           mainWindow.checkBox9.IsEnabled = true;
           mainWindow.groupBox7.IsEnabled = true;
       }
       else //UnChecked
       {
           mainWindow.checkBox9.IsEnabled = false;
           mainWindow.checkBox9.IsChecked = false;
           mainWindow.groupBox7.IsEnabled = false;
       }
} 

*注意:我知道我在上面的代码中作弊并直接与我的视图交互,但我不确定如何运行这些命令。如果这是一个问题,或者有其他方法,请告诉我如何在不与视图交互的情况下运行这些相同的命令。

现在问题来了:

更改我的代码并将命令添加到我的 ViewModel 后,TrycloneElement 函数不再起作用。在标签克隆期间的运行时,我在线收到一个XamlParseExceptionobject x = XamlReader.Load(xmlReader);,内容如下:

如果有更好的方法并且我不再需要它,我可以放弃该功能。但最终,我如何获取tabItem 的设计和功能并克隆它? (请记住,我确实在尝试纠正我的结构)

感谢您的帮助。

Leo 的答案修改

这是我正在编译的 Leo 答案的当前版本。 (有一些语法错误)

public static IList<DependencyProperty> GetAllProperties(DependencyObject obj)
{
       return (from PropertyDescriptor pd in TypeDescriptor.GetProperties(obj, new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.SetValues) })
                    select DependencyPropertyDescriptor.FromProperty(pd)
                   into dpd
                   where dpd != null
                   select dpd.DependencyProperty).ToList();
}

public static void CopyPropertiesFrom(this FrameworkElement controlToSet,
                                                   FrameworkElement controlToCopy)
{
       foreach (var dependencyValue in GetAllProperties(controlToCopy)
                    .Where((item) => !item.ReadOnly)
                    .ToDictionary(dependencyProperty => dependencyProperty, controlToCopy.GetValue))
       {
           controlToSet.SetValue(dependencyValue.Key, dependencyValue.Value);
       }
}

【问题讨论】:

  • 能贴出CircularButtonPrototypeHelpers.Command所在的代码吗?
  • 如果你想克隆它,问题是这些选项卡项的行为与其他的不同吗?您是如何创建这些选项卡项的?它们何时被克隆?
  • @Leo CircularButtonPrototype.Helpers.Command 下的代码是 ICommand 的一个实现,大约 190 行。这是我从本教程中得到的:codeproject.com/Articles/274982/Commands-in-MVVM#example1 我有 5 种不同类型的选项卡。不过,用户可以创建新的。例如,如果一个选项卡是绿色的并且用户想要创建一个新的绿色选项卡,则克隆主绿色选项卡。为了回答您的其他问题,它们是动态克隆的。
  • 嗨,Eric,听起来您好像是 WPF/MVVM 的新手,如果是这样,您可能想查看我的回答 here 中关于从 Winforms 过渡到 WPF 的链接。在您的情况下,选项卡项的所有属性,例如 IsEnabledIsChecked 都应该在您的 ViewModel(或模型)上,而您的 XAML(在这种情况下为 TabItem)只是一个非常用户友好的界面,用于向用户显示 ViewModel。要创建一个新的“选项卡”,你真的想创建一个新的 ViewModel 并将其添加到集合中,它将使用新的 TabItem 自动绘制
  • 那么我可以通过我的命令与我的主窗口进行交互了吗?

标签: c# wpf mvvm tabitem


【解决方案1】:

Here 是我在 WPF 中正确实现的动态 TabControl 的示例。

主要思想是每个Tab Item都是一个单独的小部件,包含自己的逻辑和数据,由ViewModel处理,而UI做UI必须做的事情:show data,而不是contain data .

最重要的是,所有数据和功能都在 ViewModel / Model 级别进行管理,并且由于 TabControl 绑定到 ObservableCollection,因此您只需在需要添加新元素时向该集合添加另一个元素制表符。

这消除了“克隆”用户界面或对其进行任何其他奇怪操作的需要。

【讨论】:

  • 那只是假设 TabItem 控件的 DataContext 是 TabViewModel,它在 UI 中显示数据,它并没有解决他要在哪里操作和复制 TabItem 的依赖属性,你要做什么建议在这里?附加属性?风格?数据模板?
  • 哦,所以您是说 SolidColorBrush 必须在 ViewModel 属性中,因为您说所有内容都将绑定到 ViewModel/Model 中的相关属性,这不是真的吗?
【解决方案2】:

1.) 要修复 XamlParseException,请确保您有一个像空的公共构造函数,您可能定义了一个构造函数,当您尝试序列化该对象并反序列化它时不能。您必须显式添加默认构造函数。

2.) 我不喜欢克隆这个词,但我会说,当他们想要复制时。我将手动创建一个新的选项卡项控件,然后对其进行反思。

我有这段代码

  public static IList<DependencyProperty> GetAllProperties(DependencyObject obj)
    {
        return (from PropertyDescriptor pd in TypeDescriptor.GetProperties(obj, new Attribute[] {new PropertyFilterAttribute(PropertyFilterOptions.SetValues)})
                select DependencyPropertyDescriptor.FromProperty(pd)
                into dpd where dpd != null select dpd.DependencyProperty).ToList();
    }


    public static void CopyPropertiesFrom(this FrameworkElement controlToSet,
                                               FrameworkElement controlToCopy)
    {
        foreach (var dependencyValue in GetAllProperties(controlToCopy)
                .Where((item) => !item.ReadOnly))
                .ToDictionary(dependencyProperty => dependencyProperty, controlToCopy.GetValue))
        {
            controlToSet.SetValue(dependencyValue.Key, dependencyValue.Value);
        }
    }

应该是这样的

var newTabItem = new TabItem();
newTabItem.CopyPropertiesFrom(masterTab);

【讨论】:

  • 好的,#1 效果很好。现在在实现#2 中,我需要对该函数进行哪些更改以使其特定于我的程序?我想你的意思可能是:newTabItem.CopyPropertiesFrom(masterTab);
  • 具体来说,我遇到了GetAllProperties.ToDictionarydependencyValue 的问题。
  • 这是一个扩展方法,所以请确保 CopyPropertiesFrom 在统计类中定义。
  • 只要它在static class 中就应该可以正常工作?
  • 它应该将您真正想要克隆的值复制到新项目中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-05
相关资源
最近更新 更多