为什么我的背景颜色绑定没有更新?

Why isn't my background color binding updating?

好的,我确定我的设置正确...

我有一个网格,如下所示:

<Grid Grid.Row="1" Grid.Column="1" Background="{Binding CrewSelBG[1]}">

好的。我这里有以下数组:

private string[] crewSelBG;
public string[] CrewSelBG
{
    get
    {
        return crewSelBG;
    }
    set
    {
        crewSelBG = value;
        OnPropertyChanged("CrewSelBG");
    }
}

我在视图模型的构造函数中初始化数组中的值,如下所示:

CrewSelBG = new string[26];
CrewSelBG = Enumerable.Repeat("#8a008a00", 26).ToArray();

这会将整个数组初始化为绿色。 (事实上​​ ,绿色实际上应该是#00000000,但我想看看它是否正确绑定)。 我有一个复选框,单击它会激活一个 icommand。这是我的复选框:

<CheckBox Grid.Column="0" IsChecked="{Binding CrewChecked[1]}" Margin="5,0,0,0" Command="{Binding CrewSelectCheck}" CommandParameter="01"/>

它调用的 ICommand 在此处设置:

private ICommand crewSelectCheck;

public ICommand CrewSelectCheck
{
    get
    {
        if (crewSelectCheck == null)
        {
            crewSelectCheck = new RelayCommand(param => this.CrewSelectCheckEx(param.ToString()), null);
        }
        return crewSelectCheck;
    }
}

public void CrewSelectCheckEx(string p)
{
    if (CrewChecked[Convert.ToInt32(p)])
    {
        CrewSelBG[Convert.ToInt32(p)] = "AliceBlue";//selected
    }
    else
    {
        CrewSelBG[Convert.ToInt32(p)] = "#00000000";
    }
}

OK...所以...当单击复选框并将其移动到选中状态时,它会触发将 CrewSelBG[1] 设置为 AliceBlue 的行。我在这条线上放置了一个断点,它确实触发了这条线。我又多了一行代码,CrewSelBG[1] 确实做到了,变成了 "AliceBlue"。然而,我的网格背景保持绿色(或我在构造函数中输入的任何值)。

我不明白为什么不更新???我有一个 onpropertyraised 事件(我也尝试添加以下内容,但没有用:

OnPropertyChanged("CrewSelBG[1]");

那也没用。)

有什么想法吗?

这是 ObservableCollection 更可取的地方。您应该能够将 string[] 更改为 ObservableCollection<string> 并使其正常工作。

您也可以尝试 OnPropertyChanged("CrewSelBG"),但即使可行,它也会使您对其元素的所有绑定失效。

好的,让我们做一些 WPF 101。

你实际写的是 属性 for CrewSelBG,如果你替换整个数组对象,它只会触发 WPF 更新机制 。这就是它选择初始颜色的原因,因为您创建了一个全新的数组并通过 属性 setter 对其进行分配。当然,出于某种原因,您背靠背做了两次,但这可能是工作保险,'fix' 以后的事情,所以您看起来仍然有用。

现在,仅仅因为您写了 CrewSelBG[Convert.ToInt32(p)] = "AliceBlue"; 并不意味着 WPF 会选择它。怎么可能,你使用 属性 的 getter (没有通知)并在某处替换某个数组中的项目。

WPF 实际上为您提供了一个易于使用的替代品,只需使用 ObservableCollection<>。它所做的是提供自己的 this[] 索引器,并在 that 索引器的 setter 中通知 WPF 它已更改。太完美了!

但这并不神奇——您可以轻松地自己编写它。而不是提供索引通知程序的 INotifyPropertyChanged interface, which only has one notifier for the entire sequence, you can use INotifyCollectionChanged,因此您可以告诉 WPF 只有您的集合中的索引已更改。

为了避免影响,你的 post 和评论中有很多 "I added ... in my code" 和 "I tried ... and didn't work",这让我相信你输入的是随机行随机的。 ObservableCollection<>工作。除了绑定之外,您只需确保设置了正确的 DataContext。如果你走 INotifyCollectionChanged 路线,你还必须确保首先从正确的上下文通知——即你不会把它放在你的 CrewSelectCheckEx 函数中。

问题是您正在更改 CrewSelBG 数组中的值,而不是更改数组。因此,您的 OnPropertyChanged 方法不会被调用,并且 UI 不会收到更改通知。要解决此问题,只需在更改值时手动调用 OnPropertyChanged 方法,如下所示:

public void CrewSelectCheckEx(string p)
{
    if (CrewChecked[Convert.ToInt32(p)])
    {
        CrewSelBG[Convert.ToInt32(p)] = "AliceBlue";//selected
    }
    else
    {
        CrewSelBG[Convert.ToInt32(p)] = "#00000000";
    }
    OnPropertyChanged("CrewSelBG");
}