Split one big XAML in number of Sub-XAML files

2019-02-04 06:36发布

问题:

In my WPF4 Desktop-based application there is a big block with sidebar menu that repeats in each window and takes about 70 lines of XAML. In order to improve code reuse, I would like to split XAML file in two files:

  1. XAML-file that contains code for sidebar menu (≈70 lines)
  2. Base XAML file that contains «include/reference» to XAML-file with sidebar menu code

As I understood, there are two ways to implement my problem:

  1. Use ResourceDictionary
  2. Use UserControl / CustomControl

My questions are:

  1. What is the difference between ResourceDictionary and UserControl? Could you give me examples where I have to use UserControl and where ResourceDictionary?

  2. Could you give a full code example how to include/import content of one XAML-file to other?

P.S. Here is an example of code that I want to export to separate XAML-file:

<Border Style="{StaticResource Body_SideBarMenu_Border_Settings}">
    <StackPanel Style="{StaticResource Body_SideBarMenu}">

    <TextBlock Style="{StaticResource Body_SideBarMenu_Title}"
           Text="{x:Static res:Resources.WinApp_SideBarMenu_Title}" />

        <TextBlock x:Name="SideBar_WinReports"
               Style="{StaticResource Body_SideBarMenu_Item}"
               Text="{x:Static res:Resources.DashListMarker}">
                    <Hyperlink KeyboardNavigation.TabIndex="12"
                           Style="{StaticResource Body_SideBarMenu_Item_Hyperlink}"
                           Click="Call_WinReports_Click">
                            <TextBlock Text="{x:Static res:Resources.WinApp_ModuleName_Reports}" />
                    </Hyperlink>
        </TextBlock>

    </StackPanel>
</Border>

回答1:

ResourceDictionary is just a container for your styles/templates etc. So you really have a choice between using a style (and referencing it through a ResourceDictionary) or a UserControl.

In order to differentiate between the two, ask yourself a question: are you implementing just another look for some existing control, or you are implementing something really new, which is more than just a ListView (or a Border, or a ComboBox etc.)? In the former case, use a style; in the latter, create a new UserControl.

Specifically for your case, I would go for a UserControl.


Code example (although not full)

(Please note that a template for the following code can be inserted with VS's "add new UserControl")

Xaml:

<UserControl x:Class="SomeNamespace.SidebarMenu"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <UserControl.Resources> <!-- you can define local styles here -->
        <Style x:Key="SidebarMenuTextblock" TargetType=TextBlock>
            ...
        </Style>
    </UserControl.Resources>

    <Border Background=...>
        <StackPanel>

            <TextBlock
                x:Name="Put_a_name_if_you_want_to_reference_this_item_in_code_behind"
                Style="{StaticResource SidebarMenuTextblock}"
                Text="{x:Static res:Resources.WinApp_SideBarMenu_Title}" />
            ...        </StackPanel>
    </Border>
</UserControl>

.cs:

using System;
using System.Windows;
using System.Windows.Controls;

namespace SomeNamespace
{
    public partial class SidebarMenu : UserControl
    {
        public NumericUpDown()
        {
            InitializeComponent();
        }
        ...
        // define here your properties etc,
    }
}

Now, you can use the control like that:

<Window
    x:Class="SomeOtherNamespace.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:SomeNamespace">

    <Grid>
        <controls:SidebarMenu PropertyIfYouDefinedOne="SomeValue"/>
        ...
    </Grid>

</Window>


回答2:

If you can get your hands on Expression Studio, in Expression Blend, you can simply right click on any control and convert it to an user control. As easy as that.

User controls are good for splitting the XAML file. In essence, it is used to redefine the behavior of an existing control.

However, with User Controls, you can define whole WPF Layout Controls and convert them to an User Control, with the children content inside them. This is very helpful for a project spread across multiple developers, and can also be used to emulate the behavior of an MDI, which is kind of absent in WPF.