使用绑定重用WPF布局XAML?

时间:2014-09-25 17:32:56

标签: c# wpf xaml

我一直试图为我的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 中的每一个都是一大块副本&amp;粘贴的代码,只更改了几个名称以避免重复名称。

我想以这样的方式重写代码:

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

并在其他地方定义模板

我尝试使用 DataTemplate 作为模板,并使用 ContentTemplate 将其分配给每个 TabItem ,但是虽然布局显示正确,但所有 {Bindings} 的内容丢失了。

我已经广泛搜索过,但我们还没有弄清楚我应该如何接近这一点。

我非常感谢任何能够展示如何在没有副本和附件的情况下实现绑定的演示链接。粘贴代码。

我还要感谢调试失败绑定的任何提示,除了在它们工作之前尝试解决问题。 (我很高兴用调试器调试C#,但不确定如何检查XAML的东西)

提前致谢!

2 个答案:

答案 0 :(得分:0)

您应该使用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”包含您对该特定标签项的绑定。

答案 1 :(得分:0)

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

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

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); }
    }
}

program.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中,并自动生成标签项。