【问题标题】:Dependency Property reset after setting DataContext设置 DataContext 后重置依赖属性
【发布时间】:2011-10-17 08:39:36
【问题描述】:

我在 WPF 中有一个 UserControl (AgreementDetails),具有以下 DependencyProperty 和功能:

// UserControl AgreementDetails
    public int AgreementID
        {
            get { return Convert.ToInt32(GetValue(AgreementIDProperty)); }
            set { SetValue(AgreementIDProperty, value); }

        }

    public static readonly DependencyProperty AgreementIDProperty = DependencyProperty.Register("AgreementID", typeof(int), typeof(UC1001_AgreementDetails_View), new PropertyMetadata(null));

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        int id = AgreementID;

        if (id > 0)
        {
            GetData();
            SetBindingContext();
            this.Visibility = System.Windows.Visibility.Visible;
        }
        else
        {
            this.Visibility = System.Windows.Visibility.Collapsed;
        }
    }

    private void GetData()
    {
        ConsultantServiceClient client = new ConsultantServiceClient();
        _contract = new UC1001_ActiveAgreementContract();
        _contract = client.GetAgreementDetailsByAgreementID(AgreementID);
    }

    private void SetBindingContext()
    {
        this.DataContext = _contract;
    }

我使用此 UserControl 在另一个 UserControl(仪表板)中显示为工具提示,我在其中设置了 AgreementID 属性:

// Dashboard    
<Setter Property="DataGridCell.ToolTip">
      <Setter.Value>
             <my:UC1001_AgreementDetails_View Background="#FFF" Opacity="0.88" AgreementID="{Binding Months[9].AgreementID}"/>
      </Setter.Value>
</Setter>

在 AgreementDetails 中,我使用 AgreementID 从数据库中获取一些数据以显示在 UserControl 中。我第一次这样做,一切都很顺利。但是当我在 AgreementDetails 中将传入的 WCF DataContract 设置为 datacontext 时,AgreementID 属性重置为 0,因此第二次调用将不起作用,因为显然我没有与 AgreementID = 0 的协议。我检查并在 SetBindingContext 中重置了 AgreementID ();设置 DataContext 后的方法。

我怎样才能做到让 AgreementID 属性在我在 AgreementDetails 中设置新的 dataContext 后不会重置??

如果需要,可以提供更多信息。

编辑:我现在有以下代码:

// Dependency properties
 public int AgreementID
 {
    get { return (int)GetValue(AgreementIDProperty); }
    set { SetValue(AgreementIDProperty, value); }
 }

 public UC1001_ActiveAgreementContract AgreementDetailsContract
 {
    get { return (UC1001_ActiveAgreementContract)GetValue(AgreementDetailsContractProperty); }
    set { SetValue(AgreementDetailsContractProperty, value); }

 }

    public static readonly DependencyProperty AgreementIDProperty = DependencyProperty.Register("AgreementID", typeof(int), typeof(UC1001_AgreementDetails_View), new PropertyMetadata(null));
    public static readonly DependencyProperty AgreementDetailsContractProperty = DependencyProperty.Register("AgreementDetailsContract", typeof(UC1001_ActiveAgreementContract), typeof(UC1001_AgreementDetails_View), new PropertyMetadata(null));

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        int id = AgreementID;

        if (id > 0)
        {
            GetData();
            SetBindingContext();
            this.Visibility = System.Windows.Visibility.Visible;
        }
        else
        {
            this.Visibility = System.Windows.Visibility.Collapsed;
        }
    }

    private void GetData()
    {
        ConsultantServiceClient client = new ConsultantServiceClient();
        AgreementDetailsContract = client.GetAgreementDetailsByAgreementID(AgreementID);
    }

    private void SetBindingContext()
    {
       this.DataContext = AgreementDetailsContract;
    }

我还有设置DataContext后AgreementID重置为0的问题。

另外,当我使用以下语句绑定时,我得到一个空标签:

<Label Content="{Binding RelativeSource={RelativeSource Self}, Path=AgreementDetailsContract.EndClientName}" />

已解决:

我删除了 SetDataBinding() 方法,因此 Binding 不会重置我的 DependencyProperty,并且对于我的标签的绑定,我使用了以下 Binding(而不是 RelativeSource Self):

 <Label Content="{Binding ElementName=AgreementDetails, Path=AgreementDetailsContract.EndClientName}" Grid.Column="1" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="11,0,0,0" Name="_labelEindklant" VerticalAlignment="Top" />

ElementName=AgreementDetails 是我的用户控件的名称。奇怪的是,{RelativeSource Self} 没用...

【问题讨论】:

  • 所以您将 second UserControl 的 DataContext 设置为 DataContract?并且那个 DataContract 肯定在路径 Months[9].AgreementID 处有一个非零值的属性?
  • "但是当我将传入的 WCF DataContract 设置为 UserControl 的数据上下文时,AgreementID 属性重置为 0" 当您执行上述操作时,我需要知道界面上的 AgreementID 值是多少。它也更新为 0 吗?
  • 两个 UserControl 有两个不同的契约作为它的 dataContext。问题是在工具提示 UserControl 处设置 DataContext 后,AgreementID 值重置为 0
  • 您是否检查过工具提示 DataContract 肯定在路径 Months[9].AgreementID 具有非零值的属性?
  • 工具提示 DataContract 仅使用 AgreementID 作为参数来获取正确的协议。我想我不太明白你的问题。我将在我的问题中添加更多代码,以便您更好地理解问题。

标签: c# wpf data-binding user-controls dependency-properties


【解决方案1】:

当您在用户控件中设置数据上下文时,实际上您也在重置父控件(仪表板)中的数据上下文。这是相同的上下文。因此,您的协议 ID 不再在上下文中,因此会被重置。

编辑:其实我说的不是很好。您不会影响 Dashboard 中的数据上下文,但会影响该控件中声明的 AgreementId 绑定使用的数据上下文。绑定是在仪表板控件中声明的,但绑定实际上是在您正在重置的子控件的数据上下文中查找。

在这里查看我的类似问题: Setting DataContext within UserControl is affecting bindings in parent

编辑:这就是我的意思:

// UserControl AgreementDetails
public int AgreementID
{
    get { return Convert.ToInt32(GetValue(AgreementIDProperty)); }
    set { SetValue(AgreementIDProperty, value); }
}

//The new property to bind to instead of DataContext
public UC1001_ActiveAgreementContract Agreement
{
    get { return (UC1001_ActiveAgreementContract)GetValue(AgreementProperty); }
    private set { SetValue(AgreementProperty, value); }
}

public static readonly DependencyProperty AgreementIDProperty = DependencyProperty.Register("AgreementID", typeof(int), typeof(UC1001_AgreementDetails_View), new PropertyMetadata(null));

//should really be readonly dependency property
public static readonly DependencyProperty AgreementProperty = DependencyProperty.Register("Agreement", typeof(UC1001_ActiveAgreementContract), typeof(UC1001_AgreementDetails_View), new PropertyMetadata(null));**

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    int id = AgreementID;

    if (id > 0)
    {
        GetData();
        SetBindingContext();
        this.Visibility = System.Windows.Visibility.Visible;
    }
    else
    {
        this.Visibility = System.Windows.Visibility.Collapsed;
    }
}

private void GetData()
{
    ConsultantServiceClient client = new ConsultantServiceClient();
    _contract = new UC1001_ActiveAgreementContract();
    _contract = client.GetAgreementDetailsByAgreementID(AgreementID);
}

private void SetBindingContext()
{
    this.Agreement = _contract;
}

然后在您的 AgreementDetails.xaml 中,您可能有类似的内容:

<!-- Bound to property in DataContext -->
<TextBlock Text={Binding SomeContractProperty} />

需要更改为哪个绑定:

<!-- Bound to new property on UC1001_AgreementDetails_View (UserControl) -->
<TextBlock Text={Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UC1001_AgreementDetails_View}}, Path=Agreement.SomeContractProperty} />

【讨论】:

  • 这个解释很有道理。但恐怕我无法获得解决方案,因为 datacontext 是在运行时设置的“子”-usercontrol 中的 WCF 数据合同,您如何建议我实施可行的解决方案?
  • 您需要停止在孩子中设置DataContext。而是在作为 WCF 数据合同实例的子控件(协议?)中公开一些其他属性,并改为绑定到该属性。然后,您可以在 AgreementId 更改时设置此实例,而不是设置 DataContext。
  • 我创建了另一个 DataContract 类型的 DependencyProperty,我在子 UserControl 中用作 DataContext,但是我如何将它传递给我的父 UserControl,因为我只在子 UserControl 中声明它?
  • 为什么你的父母需要它?父母唯一需要访问的是 ID。设置好之后,您可以从 WCF 创建新属性,并且您的子控件 XAML 可以绑定到它。
  • 那么你想说的是,这和我现在在 GetData() 和 SetDataBindings() 方法中所做的不一样吗?这就是我的理解,实际上......我的父母有孩子需要的协议ID。我使用 DependencyProperty 将 ID 传递给孩子。在孩子中,我从 DataContract 中的 WCF 主机获取正确的数据,然后将该 DataContract 作为 DataSource 绑定到我的孩子。此绑定导致协议ID 在父项中消失,因为由于子项中的新绑定,父项中的绑定会重置。
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 2011-01-03
  • 2017-05-04
  • 1970-01-01
  • 2013-07-19
  • 2014-08-14
相关资源
最近更新 更多