无法绑定到DataContext的属性

3

这是我第一次发布问题。我研究了整整一天,但仍然不知道为什么这个绑定不起作用。

我想让一个标签(Label)显示对象“hotspot”的名称,该对象是名为Plan的类实例的属性。有多个计划(Plan),每个计划包含多个热点(hotspot)。当我单击一个热点时,属性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 吗? - Anatoliy Nikolaev
HotSpot.Name是一个字符串,在HotSpot类中不会改变,因此无需为其实现INotifyPropertyChanged接口。当lstPlans_SelectionChanged被触发时,canvas.Plan永远不会为空。只有在窗口加载时才为空。 - Youszef
请在Visual Studio的输出窗口中查看并告诉我们那里有什么错误。 - Sheridan
感谢您的评论。没有错误。只有lblHotSpotName的内容不显示所选热点的名称。但我认为我知道这个问题的全部原因。由于Plan类中的变量SelectedHotSpot作为对象始终在变化,我不认为我可以将其绑定到该变量。它只保留在lstPlans_SelectionChanged触发时设置的对象的引用,该对象为空。 - Youszef
3个回答

1
我不能确定是否完全理解了您的问题,因为您的问题有些不清楚。但是您不能在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在运行时可能为null,因为它有不同的对象。我已经尝试过这个方法,但它仍然是null。我之所以没有在XAML中这样做,是因为ListBox不包含Plan对象,而是包含ID,我之后使用这些ID从数据库中获取数据来创建一个Plan对象。出于性能方面的考虑,我这样做了。 - Youszef

0

我不确定这样做是否有帮助,但在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为null。当我单击热点时,绑定未能看到该属性的更改并仍保持为null。 - Youszef
1
@Youszef:在*lstPlans_SelectionChanged*中,SelectedHotSpot是否为空?如果是,则绑定也为空。 - Anatoliy Nikolaev
在触发器的那一刻,SelectedHotSpot是空值。我应该如何解决这个问题?或者我应该在Plan类中创建一个公共字符串,以获取所选SelectedHotSpot.Name的值,并将其绑定到该公共字符串。 - Youszef

0

在给定的代码中看不到任何问题(尽管,对于 .Name 的 Raise property changed 不是必需的)。

我建议确认 selectedHotSpot 总是有一些实例并且不是 null。 尝试修改您的 plan class 并设置:

selectedHotSpot = new HotSpot(Name="Default")

然后你应该在标签中看到“默认”。


是的,这个确实有效。那么我就无法绑定到一个对象不断变化的变量了吗? - Youszef
1
绑定是到对象的实例。如果该对象为空,则在用户界面上什么也不会显示。 - Manish Basantani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接