WPF 绑定选项卡控件选项卡项



我对 WPF 中的 MVVM 相对较新,并且几天来一直在尝试解决一个问题。 我正在使用dragablz选项卡控件并绑定ItemsSource,这是一个可观察的对象列表。 但是,选项卡项的内容是用户控件;它的数据上下文是 null 。 我创建了一个简单的设置来演示我遇到的问题:

模型

/视图模型类:

public class Item
{
    public string Header { get; set; }
    public ItemContent Body { get; set; }
}
public class ItemContent
{
    public string Name { get; set; }
    public string Description { get; set; }
}
class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public ObservableCollection<Item> Items { get; set; }       
}

主窗口 XAML

<Window x:Class="WpfTestApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfTestApplication"
    xmlns:views="clr-namespace:WpfTestApplication.ViewModels"
    xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
    xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <views:MainWindowViewModel />
</Window.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Button Name="btnAdd" Content="Add" Click="btnAdd_Click" />
    <dockablz:Layout Grid.Row="1">
        <dragablz:TabablzControl HeaderMemberPath="Header" ItemsSource="{Binding Items}" SelectedIndex="1">
            <dragablz:TabablzControl.ContentTemplate>
                <DataTemplate DataType="{x:Type views:Item}">
                    <local:TabItemControl />
                </DataTemplate>
            </dragablz:TabablzControl.ContentTemplate>
        </dragablz:TabablzControl>
    </dockablz:Layout>
</Grid>
</Window>

选项卡项 XAML

<UserControl x:Class="WpfTestApplication.TabItemControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WpfTestApplication"
         xmlns:views="clr-namespace:WpfTestApplication.ViewModels"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <views:ItemContent />
</UserControl.DataContext>
<Grid>
    <TextBox Text="{Binding Body}" />
</Grid>
</UserControl>

和btnAdd_Click事件

请注意,我没有在我的实际代码中使用它,但这是一种快速而肮脏的方式,无需添加命令即可动态添加选项卡项。

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        ((ViewModels.MainWindowViewModel)DataContext).Items.Add(new ViewModels.Item() { Header = "New One", Body = new ViewModels.ItemContent() { Name = "This One" } });
    }

Will 在对原始问题的评论中回答了我的问题。我用他的回答写了另一篇文章:https://stackoverflow.com/a/44729258/1228 做以下事情。

我从我的用户控件中删除了这个:

<UserControl.DataContext>
    <views:ItemContent />
</UserControl.DataContext>

然后,我在 UserControl 代码后面添加了一个名为 Body 的依赖项属性:

public static readonly DependencyProperty BodyProperty = 
DependencyProperty.Register("Body", 
                            typeof(ViewModels.ItemContent), 
                            typeof(TabItemControl), 
                            new PropertyMetadata(null));
public ViewModels.ItemContent Body
{
    get
    {
        return (ViewModels.ItemContent)GetValue(BodyProperty);
    }
    set
    {
        SetValue(BodyProperty, value);
    }
}
public string BodyText {
    get
    {
        return Body?.Name;
    }
    set
    {
        if (Body != null)
        {
            Body.Name = value;
        }
    }
}

我更新了主窗口的选项卡控件内容模板,如下所示:

<dragablz:TabablzControl.ContentTemplate>
    <DataTemplate DataType="{x:Type views:ItemContent}">
        <local:TabItemControl Body="{Binding Body}" />
    </DataTemplate>
</dragablz:TabablzControl.ContentTemplate>

并将我的用户控件更改为使用 BodyText 属性作为文本框的值:

<Grid x:Name="LayoutRoot">
    <TextBox Text="{Binding BodyText}" />
</Grid>

最新更新