【问题标题】:Cannot bind to a Property of DataContext无法绑定到 DataContext 的属性
【发布时间】:2014-03-24 07:52:26
【问题描述】:

这是我第一次发布问题。我正在研究这个问题大约一整天,但不明白为什么这个绑定不起作用。

我想要一个标签来显示对象“热点”的名称,它是名为 Plan 的类实例的属性。有多个计划,每个计划包含多个热点。当我单击一个热点时,属性Plan.SelectedHotSpot 将此单击的热点设置为值。如果没有选择 HotSpot,它将变为 null。

XAML:

<Label Name="lblHotSpotName" />

从ListBox中选择Plan时的MainWindow代码:

private void lstPlans_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    canvas.Plan = PlanBLL.GetPlanByID(plans[lstPlans.SelectedIndex].ID);
    lblHotSpotName.DataContext = canvas.Plan;
    lblHotSpotName.SetBinding(Label.ContentProperty, "SelectedHotSpot.Name");
}

计划课:

public class Plan : INotifyPropertyChanged
{
    private HotSpot selectedHotSpot;

    public HotSpot SelectedHotSpot
    {
        get { return selectedHotSpot; }

        set
        {
            selectedHotSpot = value;
            OnPropertyChanged("SelectedHotSpot");
            OnPropertyChanged("SelectedHotSpot.Name");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
 }

当我点击热点lblHotSpotName 保持空白时,此代码似乎不起作用。 在我看来,加载计划时 SelectedHotSpot 为空,因此它不会绑定到加载计划后选择的热点对象。 我的暗示对吗?此绑定需要有一个不为空的现有对象。而当对象发生变化时,我们需要重新定义从标签到Plan.SelectedHotSpot的绑定。

感谢您的帮助。

【问题讨论】:

  • HotSpot.Name 属性支持INotifyPropertyChanged?当lstPlans_SelectionChanged被触发时,canvas.Plan不是null
  • HotSpot.Name 是一个字符串,不会在 HotSpot 类中更改,因此无需为此实现 INotifyPropertyChanged 接口。当触发 lstPlans_SelectionChanged 时,canvas.Plan 永远不会为空。只有在加载窗口时它才为空。
  • 请查看您在 Visual Studio 中的输出窗口,并告诉我们您看到的错误。
  • 感谢您的评论。没有错误。只有 lblHotSpotName 的内容不显示 SelectedHotSpot 的名称。但我想我知道这个问题的全部原因。由于 Plan Class 中的变量 SelectedHotSpot 一直保持变化的对象,我认为我无法绑定到它。它只是保留对在触发 lstPlans_SelectionChanged 时设置的对象的引用,该对象为空。

标签: c# wpf xaml data-binding datacontext


【解决方案1】:

在给定的代码中看不到任何问题(尽管不需要为 .Name 更改 Raise 属性)。

我建议确认selectedHotSpot 总是有一些实例并且不为空。 尝试修改您的计划类并设置:

selectedHotSpot = new HotSpot(Name="Default")

您应该会在标签中看到“默认”。

【讨论】:

  • 是的,这个确实有效。所以我无法绑定到对象一直在变化的变量?
  • 绑定到一个对象实例。如果该对象为 null,则 UI 上不会出现任何内容。
【解决方案2】:

我不能确定我是否完全正确地理解了您的问题,因为您的问题有些不清楚,但是您能否不只是将数据绑定到 XAML 中的 Label.Content 属性?如果您想数据绑定当前在ListBox 中选择的Plan 项目的SelectedHotSpot.Name 属性,那么您应该能够执行以下操作:

<Label Name="lblHotSpotName" 
   Content="{Binding SelectedItem.SelectedHotSpot.Name, ElementName=lstPlans}" />

更新>>>

您最好还是为您的Binding 使用 XAML。添加要绑定的 string 属性,然后在您的 lstPlans_SelectionChanged 处理程序中更新它:

<Label Name="lblHotSpotName" Content="{Binding SelectedItemHotSpotName}" />

...

private void lstPlans_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    canvas.Plan = PlanBLL.GetPlanByID(plans[lstPlans.SelectedIndex].ID);
    SelectedItemHotSpotName = canvas.Plan.SelectedHotSpot.Name;
}

【讨论】:

  • 问题是 SelectedHostSpot 可以为空,因为在运行时有不同的对象。我试过这个。但它仍然为空。为什么我没有这样做是 XAML 是因为 ListBox 不包含计划对象,而是包含 ID,我之后使用它从数据库中获取数据以使用它创建计划对象。我这样做是出于性能原因。
【解决方案3】:

我不确定它是否有帮助,但在lstPlans_SelectionChanged 试试这个Binding

var myBinding = new Binding();

myBinding.Path = new PropertyPath("SelectedHotSpot.Name");
myBinding.Source = canvas.Plan;
lblHotSpotName.SetBinding(Label.ContentProperty, myBinding);

如果SelectedHotSpot.Name不改变,则不需要此行时:

OnPropertyChanged("SelectedHotSpot.Name");

SelectedHotSpot 属性声明中。

【讨论】:

  • 不幸的是它不起作用。谢谢你的建议。所以当我打开计划时。 SelectedHotSpot 为空。当我单击热点时。绑定看不到该属性的变化并保持为空。
  • @Youszef: SelectedHotSpotlstPlans_SelectionChanged 中为空?如果是,那么 Binding 也是 null。
  • 是 SelectedHotSpot 在触发时为空。有什么办法可以解决这个问题。或者我应该在类 Plan 中创建一个公共字符串,在选择时获取 SelectedHotSpot.Name 值。并绑定到该公共字符串。
猜你喜欢
  • 1970-01-01
  • 2013-07-25
  • 2011-07-23
  • 1970-01-01
  • 2013-03-30
  • 2014-09-22
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多