首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >wpf mvvm嵌套用户控件datacontext

wpf mvvm嵌套用户控件datacontext
EN

Stack Overflow用户
提问于 2019-09-17 13:59:16
回答 1查看 1.1K关注 0票数 2

我对嵌套datacontext user-controls有一个问题。问题是ViewModel中的模型绑定在第一个user-controlDependencyProperty上。在第一个user-control中是第二个user-control。第二个user-control也有一个DependencyProperty。第一个user-control绑定在第二个user-control的那个DependencyProperty上。

主视图:

代码语言:javascript
复制
<UserControl x:Class="XXX.XXX.Hmi.Views.L1SetupViewerView"
             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:prism="http://prismlibrary.com/"
             xmlns:uc="clr-namespace:XXX.XXX.Hmi.UserControls"
             d:DesignHeight="450"
             d:DesignWidth="800"
             prism:ViewModelLocator.AutoWireViewModel="True"
             Background="{DynamicResource BaseBrush}"
             Foreground="{DynamicResource TextBrush}"
             mc:Ignorable="d">
.
.
.
    <GroupBox Grid.Row="1" Header="Entry Section">
        <uc:L1SetupViewerEntrySectionView Margin="8" Setup="{Binding L1Setup}" />
    </GroupBox>
.
.
.
</UserControl>

MainViewModel:

代码语言:javascript
复制
public class L1SetupViewerViewModel : ViewModelBase
{
    private L1Setup _l1Setup;
    private Pdi _pdi;

    public L1SetupViewerViewModel()
    {
        Title = LanguageProvider.Instance.GetValue("L1SetupViewer_Window_Title");
        LanguageProvider.Instance.UiCultureChanged += Instance_UiCultureChanged;
    }

    #region Properties

    public L1Setup L1Setup
    {
        get { return _l1Setup; }
        set { SetProperty(ref _l1Setup, value); }
    }
    public Pdi Pdi
    {
        get { return _pdi; }
        set { SetProperty(ref _pdi, value); }
    }

    #endregion

    #region Navigation

    public override void OnNavigatedTo(NavigationContext navigationContext)
    {
        if (navigationContext.Parameters.ContainsKey("L1Setup"))
        {
            L1Setup = navigationContext.Parameters.GetValue<L1Setup>("L1Setup");
        }

        if (navigationContext.Parameters.ContainsKey("Pdi"))
        {
            Pdi = navigationContext.Parameters.GetValue<Pdi>("Pdi");
        }
    }

    #endregion

    private void Instance_UiCultureChanged(object sender, EventArgs e)
    {
        Title = LanguageProvider.Instance.GetValue("L1SetupViewer_Window_Title");
    }
}

First UserControl:

代码语言:javascript
复制
<UserControl x:Class="XXX.XXX.Hmi.UserControls.L1SetupViewerEntrySectionView"
             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:uc="clr-namespace:XXX.XXX.Hmi.UserControls"
             d:DesignHeight="450"
             d:DesignWidth="800"
             mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
            <ColumnDefinition Width="*" SharedSizeGroup="c" />
        </Grid.ColumnDefinitions>
        <uc:L1SetupViewerCellControl Title="Over Speed"
                                     Grid.Row="0"
                                     Grid.Column="0"
                                     Margin="0,0,5,0"
                                     Value="{Binding Setup.EnOveSpd}" />
         .
         .
         .
    </Grid>
</UserControl>

First UserControl CodeBehind:

代码语言:javascript
复制
public partial class L1SetupViewerEntrySectionView : UserControl
{
    public L1Setup Setup
    {
        get { return (L1Setup)GetValue(SetupProperty); }
        set { SetValue(SetupProperty, value); }
    }
    public static readonly DependencyProperty SetupProperty =
        DependencyProperty.Register("Setup", typeof(L1Setup), typeof(L1SetupViewerEntrySectionView), new PropertyMetadata(null));

    public L1SetupViewerEntrySectionView()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

第二UserControl:

代码语言:javascript
复制
<UserControl x:Class="XXX.XXX.Hmi.UserControls.L1SetupViewerCellControl"
             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"
             d:DesignHeight="450"
             d:DesignWidth="800"
             mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0"
                   Margin="0,0,3,0"
                   Text="{Binding Title}" />
        <TextBox Grid.Column="1" Text="{Binding Value}" />
    </Grid>
</UserControl>

Second UserControl CodeBehind:

代码语言:javascript
复制
public partial class L1SetupViewerCellControl : UserControl
{
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(L1SetupViewerCellControl), new PropertyMetadata(string.Empty));

    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(string), typeof(L1SetupViewerCellControl), new PropertyMetadata(string.Empty));

    public L1SetupViewerCellControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

如果运行应用程序,则会得到以下绑定错误:

代码语言:javascript
复制
System.Windows.Data Error: 40 : BindingExpression path error: 'L1Setup' property not found on 'object' ''L1SetupViewerCellControl' (Name='')'. BindingExpression:Path=L1Setup.EnPor1OutDia; DataItem='L1SetupViewerCellControl' (Name=''); target element is 'L1SetupViewerCellControl' (Name=''); target property is 'Value' (type 'String')

我在stackOverflow上尝试了几个答案,没有什么对我有用,我也不明白有什么不对。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-17 14:04:55

this.DataContext = this上设置L1SetupViewerEntrySectionView会破坏来自L1SetupViewerView的数据上下文的继承,这就是为什么绑定到L1Setup失败的原因。

与其在代码背后显式设置DataContext,不如在UserControl中设置根元素的DataContext,如下所示:

代码语言:javascript
复制
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}>

在每个绑定上...or源:

代码语言:javascript
复制
<uc:L1SetupViewerCellControl ... 
    Value="{Binding Setup.EnOveSpd, RelativeSource={RelativeSource AncestorType=UserControl}}" />

同样的情况也适用于L1SetupViewerCellControl,即从构造函数中删除this.DataContext = this并使用RelativeSource绑定到Value属性。

代码语言:javascript
复制
<TextBox Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" />
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57975922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档