【问题标题】:How can I use a view from a framework in an application? (WPF MVVM)如何在应用程序中使用框架中的视图? (WPF MVVM)
【发布时间】:2013-08-27 13:29:54
【问题描述】:

我在一个自定义框架中创建了一个BaseWindowView 和一个BaseViewModel,我想在我的所有应用程序中将其用作基础。

BaseViewModel 中,例如,我有一个允许我添加按钮的方法。我可以定义CommandButtonImageLabelString。下面是该方法的调用示例代码:

AddButton(OpenAnyTabCommand, "../Images/image.png", "LabelString");

在我的BaseWindowView 中,我有一个RibbonMenue,其中显示了我在BaseViewModel 中定义的所有RibbonButtons

<ItemsControl x:Name="CButtons" ItemsSource="{Binding Buttons}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel x:Name="ButtonStackPanel" Orientation="Horizontal">
            </StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ribbon:RibbonButton
                x:Uid="Button"
                LargeImageSource="{Binding Path=ImageString}"
                Label="{Binding Path=LabelString}"
                Command="{Binding Path=ButtonCommand}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我在一个示例项目中有这个,它工作正常。现在我想将BaseWindowViewBaseViewModel 外包给一个框架并从那里使用它。

我的计划是:在我的每个应用程序中,我想将BaseWindowView 设置为我的应用程序的MainWindow。在这个应用程序本身中,我只想拥有一些UserControls,它们应该在我的BaseWindowView 中显示为选项卡。我在BaseViewModel 中定义的按钮应该调用定义的Command,它会打开一个新选项卡并在Command 后面显示ViewModel

那么解决我的问题的最佳方法是什么?我知道 XAML 中没有“经典继承”。我可以在框架视图中定义App.xaml 中的StartUpUri 还是“有点”棘手?

作为补充:我发现我可以在App.xaml 中为TabItems(即UserControls)定义DataTemplate,如下所示:

<DataTemplate DataType="{x:Type ViewModel:AnyViewModel}">
    <view:TabItemAny/>
</DataTemplate>

@Sheridan:这是关于BaseWindowView 的问题。

【问题讨论】:

  • 问题不是很清楚:问题是什么?你知道没有 XAML 继承这样的东西吗?
  • 是的,我知道没有“经典继承”。我的问题是我怎么能做一些像视图继承这样的事情。我想将我的Framework-View 显示为我的应用程序中的主窗口,并添加一些用户控件以在此窗口中打开选项卡。
  • @Sheridan,这是问题

标签: c# .net wpf xaml mvvm


【解决方案1】:

好的,所以首先,让我们使用您的BaseWindowView 地址as MainWindow

首先,在App.xaml 文件中,从Application 定义中删除StartupStartupUri 属性的声明。然后在App.xaml.cs类中,添加一个启动处理程序:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    BaseWindowView baseWindowView = new BaseWindowView();
    baseWindowView.Show();
}

这将打开您的Window,而不是MainWindow

现在来看视图继承...如您所知,WPF 中没有这样的东西,但是(某种)有一种方法可以解决这个问题。如果如您所说,您的所有视图都是基于UserControl,那么我们可以使用ContentControl 对象来显示它们,前提是存在相关的DataTemplate 对象。

这基本上意味着如果您想使用特定的Window 作为视图的外部模板,那么您可以添加ContentControl 来显示视图。例如,我有一个动画Window,它显示为带有按钮的对话控件,我将几个不同的UserControls 绑定到这些按钮,以便它们具有相同的整体外观。

在 xaml 中:

...
<Border CornerRadius="3.5" BorderBrush="{StaticResource TransparentBlack}" 
    BorderThickness="1" Padding="1">
    <ContentControl Content="{Binding ViewModel, RelativeSource={RelativeSource 
        FindAncestor, AncestorType={x:Type Controls:AnimationWindow}}}" />
</Border>
...

Window 后面的代码中:

public static readonly DependencyProperty ViewModelProperty = DependencyProperty.
    Register("ViewModel", typeof(BaseViewModel), typeof(AnimationWindow));

public BaseViewModel ViewModel
{
    get { return (BaseViewModel)GetValue(ViewModelProperty); }
    set { SetValue(ViewModelProperty, value); }
}

使用这个类,我可以绑定到 xaml 中的这个 ViewModel 属性,或者从通过构造函数传入的值设置它。由于我所有的视图模型都扩展了这个 BaseViewModel 类,因此我可以将此属性设置为其中的任何一个。

更新>>>

使用ContentControlDataTemplates 连接视图/视图模型的意义在于我们摆脱了“硬编码”。我可以在每个应用程序中使用此设置,并且我依赖于使用任何特定的实现。

现在,如果您说您确实想在所有不同的应用程序中使用 same 视图/视图模型配对,那么您应该将 DataTemplates 用于连接视图/在单独的 Resources xaml 文件中查看模型。这样,您可以将此文件合并到您需要的应​​用程序中的 App.xaml Resources 部分中,而不是在您不需要时:

<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="ViewModelToViewDataTemplates.xaml"/>
      <ResourceDictionary>
          <!-- Add your normal resources here -->
      </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

【讨论】:

  • 感谢您的回答!添加启动处理程序工作正常。你知道我是否可以在我的BaseViewWindow 中添加一个用户控件(它应该是一个组合框)的调用,但用户控件本身是在我的应用程序中定义的?在我的应用程序中,UserControl 的 DataContext 也应该是 ViewModel
  • 嘿。 '你知道我是否可以在我的BaseViewWindow 中添加UserControl(应该是ComboBox)的调用'是什么意思?
  • 我想在我的BaseViewWindow 中有类似的东西:&lt;View:UserControlPerson x:Name="UcPerson" DataContext="{Binding Path=PersonViewModel}"/&gt;。但是 UserControl 本身和 PersonViewModel 是在应用程序中而不是在框架中。
猜你喜欢
  • 1970-01-01
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多