【问题标题】:XAML GridView, ObservableCollection and changing an item's propertiesXAML GridView、ObservableCollection 和更改项目的属性
【发布时间】:2014-06-23 14:44:54
【问题描述】:

我有一个类,派生自 BindableBase,它包含两个属性:

    private string sourceCallNumber;
    public string SourceCallNumber
    {
        get { return sourceCallNumber; }
        set { SetProperty(ref sourceCallNumber, value); }
    }

    private string sourceMediaType;
    public string SourceMediaType
    {
        get { return sourceMediaType; }
        set { SetProperty(ref sourceMediaType, value); }
    }

我有一个 ObservableCollection,其中包含许多使用该类的项目。

我有一个 GridView,我将 ItemsSource 设置为指向 ObservableCollection。

我的问题是,如果我更改其中一项的 SourceMediaType 的值,则显示不会更新。我已经进行了调试,并且可以确认更改值会导致 OnPropertyChanged 为该属性触发。

我已经阅读了很多关于类似问题的 SO 问题和答案,但我很困惑我需要做什么才能使其正常工作。

我的理解是,虽然 ObservableCollection 本身在属性更改时不会做任何事情,但如果项目本身触发了 OnPropertyChanged,那么应该会更新显示。

(我读到的一个答案建议使用提供的名为 TrulyObservableCollection 的代码,但我遇到的问题是所有内容都会刷新,而不仅仅是已更新的一项)。

请问我有什么遗漏或误解吗?

谢谢。

【问题讨论】:

  • 你解释的方式没有错。您确定 Binding 不是 OneTime 吗?能否也添加 Xaml 代码?
  • 我将在您的 SetProperty 函数中进行一次疯狂的飞跃,您不应该传递一个表示正在更改的实际属性的字符串吗?除非您从字段名称中获取属性名称(这将要求所有人都遵循相同的模式)。
  • @Reza - 不,绑定不是一次性的。
  • @RodrigoSilva 你走在正确的道路上。 SetProperty 确实确实从字段名称中获取了属性名称......但这不是 XAML 绑定的内容。 XAML 绑定到一个不同的属性,该属性在文本周围设置了一些格式。明确提及该名称可以解决问题。我需要更聪明地使用 XAML 并使用转换器而不是不同的属性。

标签: c# xaml gridview observablecollection


【解决方案1】:

C# 应用程序应实现 INotifyCollectionChanged 和 System.Collections.IList(不是 IList Of T)。

public class NameList : ObservableCollection<PersonName>
{
    public NameList() : base()
    {
        Add(new PersonName("Willa", "Cather"));
        Add(new PersonName("Isak", "Dinesen"));
        Add(new PersonName("Victor", "Hugo"));
        Add(new PersonName("Jules", "Verne"));
    }
  }

  public class PersonName
  {
      private string firstName;
      private string lastName;

      public PersonName(string first, string last)
      {
          firstName = first;
          lastName = last;
      }

      public string FirstName
      {
          get { return firstName; }
          set { firstName = value; }
      }

      public string LastName
      {
          get { return lastName; }
          set { lastName = value; }
      }
  }

GridView

【讨论】:

【解决方案2】:

@RodrigoSilva 让我走上了正确的道路……引用这些值的 XAML 是这样的:

            <StackPanel>
                <TextBlock Text="{Binding DisplayCallNumber}" Style="{StaticResource TitleTextBlockStyle}" Visibility="{Binding GotCallNumber, Converter={StaticResource DisplayIfTrue}}" Margin="0,0,0,10"/>
                <TextBlock Text="{Binding DisplayMediaType}" Style="{StaticResource ItemTextStyle}" Visibility="{Binding GotMediaType, Converter={StaticResource DisplayIfTrue}}" Margin="0,0,0,10"/>
            </StackPanel>

它不直接引用底层属性 SourceCallNumber 和 SourceMediaType。因此,尽管 OnPropertyChanged 正确触发了 SourceCallNumber 和 SourceMediaType,但这不会导致显示更新,因为这不是 XAML 指向的内容。

将对 SetProperty 的调用显式更改为:

SetProperty(ref sourceCallNumber, value, "DisplayCallNumber");

修复了问题,但不是一个好的修复,因为应用程序的某些其他部分实际上可能绑定到 SourceCallNumber,并且在此更改后不会获得属性更新。好的解决方法是使用转换器,如http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh464965.aspx 中所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    相关资源
    最近更新 更多