无法找到父对象

时间:2018-02-06 01:09:11

标签: c# wpf xaml mvvm data-binding

我尝试制作一个TabControl,其中每个UserControl都有一个单独的ViewModel。

我已经在我的XAML中声明了这样:

<TabControl Margin="10,10,10,40" ItemsSource="{Binding Test}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" FontSize="16" Padding="5"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

正如您所见,我试图通过位于其中的属性获取标签名称的视图模型:

public class GeneralTabViewModel : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public GeneralTabViewModel()
    {
        Name = "Name";
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

与保存TabControl的窗口关联的视图模型声明如下:

public class SettingsViewModel
{
    public ObservableCollection<UserControl> Test { get; set; }

    public SettingsViewModel()
    {
        Test = new ObservableCollection<UserControl>
        {
            new GeneralTab(),
            new GeneralTab()
        };
    }
}

像这样构建程序会为2个选项卡生成一个空标题。

如何将TextBlock的{​​{1}}属性绑定到位于Text的视图模型中的Name属性?

如果我将UserControl类型从ItemSource更改为ObservableCollection<UserControl>我将能够访问该媒体资源,但我如何将ObservableCollection<GeneralTabViewModel>可视化为?< / p>

1 个答案:

答案 0 :(得分:1)

在SettingsViewModel中使用UserControl是错误的。它应该有一个GeneralTabViewModels的集合:

public class SettingsViewModel
{
    public ObservableCollection<GeneralTabViewModel> Test { get; }

    public SettingsViewModel()
    {
        Test = new ObservableCollection<GeneralTabViewModel>
        {
            new GeneralTabViewModel { Name = "Tab 1" },
            new GeneralTabViewModel { Name = "Tab 2" }
        };
    }
}

然后,您将在TabControl的ItemTemplate中使用UserControl:

<TabControl Margin="10,10,10,40" ItemsSource="{Binding Test}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <GeneralTab TabName="{Binding Name}"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

为了使其工作,重要的是GeneralTab不显式设置其DataContext属性。它可能看起来像这样:

<UserControl x:Class="YourNamespace.GeneralTab" ...>
    <Grid>
        <TextBlock FontSize="16" Padding="5"
                   Text="{Binding TabName,
                          RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    </Grid>
</UserControl>

在其代码中包含此依赖项属性:

public static readonly DependencyProperty TabNameProperty =
    DependencyProperty.Register(nameof(TabName), typeof(string), typeof(GeneralTab));

public string TabName
{
    get { return (string)GetValue(TabNameProperty); }
    set { SetValue(TabNameProperty, value); }
}