使用绑定重用WPF布局XAML

本文关键字:布局 XAML WPF 绑定 | 更新日期: 2023-09-27 18:24:36

我一直在努力为我的WPF应用程序重用布局代码。

我正在尝试制作一个XML编辑器,让您可以打开多个文件(通过选项卡)。

我的情况如下:

<TabControl>
  <TabItem>
    // Layout XAML with various {Binding} sources (File 1)
  </TabItem>
  <TabItem>
    // Layout XAML with various {Binding} sources (File 2)
  </TabItem>
  <TabItem>
    // Layout XAML with various {Binding} sources (File 3)
  </TabItem>
</TabControl>

这是有效的;然而,三个TabItems中的每一个都是一个巨大的副本&粘贴的代码,只更改了几个名称以避免重复名称。

我想以这样一种方式重写代码,使类似的事情成为可能:

<TabControl>
  <TabItem>
    // Reference to Template
  </TabItem>
  <TabItem>
    // Reference to Template
   </TabItem>
  <TabItem>
    // Reference to Template
  </TabItem>
</TabControl>

并在其他地方定义模板

我尝试使用DataTemplate作为模板,并将其分配给具有ContentTemplateabItem,但尽管布局显示正确,但所有{Bindings}都丢失了。

我在谷歌上搜索了很多,但都不知道该怎么处理。

我将非常感谢任何演示链接,它将展示如何在没有复制的情况下实现绑定;粘贴代码。

我也很感激任何调试失败绑定的技巧,除了尝试直到它们工作为止。(我很乐意用调试器调试C#,但不知道如何检查XAML内容)

提前感谢!

使用绑定重用WPF布局XAML

您应该使用Window的ViewModel,用ObservableCollection来表示选项卡项。

<TabControl ItemsSource="{Binding Path=TabItems, Mode=OneTime}" SelectedValue="{Binding Path=SelectedTab, Mode=TwoWay}">
    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Header" Value="{Binding Header}"/>
            <Setter Property="Content" Value="{Binding}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border Name="Border" Margin="0,0,-4,0" BorderThickness="1">
                                <ContentPresenter
                                    x:Name="ContentSite"
                                    HorizontalAlignment="Center"
                                    Margin="12,2,12,2"
                                    VerticalAlignment="Center"
                                    ContentSource="Header"
                                    RecognizesAccessKey="True"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                        etc...
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                        etc...
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.ItemContainerStyle>
</TabControl>

然后,每个选项卡项本身就是一个视图模型,其中包含每个选项卡所需绑定的所有数据

public ObservableCollection<TabItemViewModel> TabItems
{
    get
    {
        return m_SuspendTabItems;
    }
    private set
    {
        if (Equals(m_SuspendTabItems, value))
        {
            return;
        }
        m_SuspendTabItems = value;
        NotifyPropertyChanged(s_SuspendTabItems);
    }
}

将在您的主WindowViewModel上。要添加新选项卡,只需调用TabItems.add(new TabItemViewmodel());。

其中"TabItemViewModel"包含该特定选项卡项的绑定。

我建议编写一个自定义UserControl,其中包含您现在正在复制粘贴的所有内容,并将此UserControl添加到选项卡项中。将所需的源作为依赖属性添加到此UserControl。现在,您可以从TabControl访问它,而不会丢失绑定。

我做了一个快速的非工作示例:

MyControl.xaml

<UserControl Name=this>
    <StackPanel>
        <TextBox Text={Binding Something, ElementName=this} />
    </StackPanel>
</UserControl>

MyControl.xaml.cs

public partial class MyControl : UserControl
{
    public static readonly DependencyProperty SomethingProperty = DependencyProperty.Register("Something", typeof(string), typeof(MyControl));
    public string KeyType
    {
        get { return (string)GetValue(SomethingProperty ); }
        set { SetValue(SomethingProperty , value); }
    }
}

程序.xaml

<Window>
    <TabControl>
        <TabItem>
            <MyControl Something={Binding Anything[0] />
        </TabItem>
        <TabItem>
            <MyControl Something={Binding Anything[1] />
        </TabItem>
        //...
    </TabControl>
</Window>

program.xaml.cs

//...
public string[] Anything { get; set; }
//...

请注意,这只是一个非常简单的例子。您可以很容易地将上面提到的所需模型添加到ObservableCollection中,并从中自动生成选项卡项。