【问题标题】:XAML Gridview is not updating when property of item scource changes项目来源的属性更改时 XAML Gridview 不更新
【发布时间】:2017-08-10 03:49:22
【问题描述】:

更新:

这似乎是两个独立的绑定,一个在内存中的对象和 GridView 之间,一个在内存中的对象和文本框之间。

文本框将更改传播回内存中的对象,但这些更改无法反映在 GridView 的显示中。

原文:

我一直在做一些研究并尝试了一些不同的技术,但我无法更新我的网格视图。目标是让 GridView 显示项目图块列表,数据绑定到 ObservableCollection。在同一页面上的 GridView 下方,是一个用于编辑 GridView 中的项目的表单。当用户在 GridView 中选择一个项目时,表单的文本框(和其他控件)会自动填充 GridView 中所选项目的属性值。修改控件的值然后更改所选 GridView 项的属性值。

我有一个会议数据类型,其中包括一个名称属性(字符串类型)。 “会议”是 ObservableCollection 类型。

gridview 看起来像这样(为简洁起见,此处省略了一些属性):

<GridView Style="{StaticResource HorizontalScrollGridView}"
                  Name="ConferencesGridView"
                  ItemsSource="{Binding Conferences, Mode=TwoWay}"
                  SelectionChanged="ConferencesGridView_SelectionChanged">

在 GridView 内部,是一个如下所示的项目模板:

<GridView.ItemTemplate>
                <DataTemplate x:DataType="data:Conference">
                    <Grid Height="150"
                          Width="150">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="*"></RowDefinition>
                        </Grid.RowDefinitions>

                        <TextBlock Grid.Row="0"></TextBlock>
                        <TextBlock Grid.Row="1"
                                   Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                   TextWrapping="WrapWholeWords"></TextBlock>
                    </Grid>
                </DataTemplate>
            </GridView.ItemTemplate>

请注意,正确定义了 XML 命名空间“数据:”以引用定义“会议”数据类型的命名空间。没有编译错误,只有在程序运行时出现意外(或在这种情况下完全丢失)行为。

最后,在同一页面上,但不在 GridView 内,是用于编辑当前选定项目的表单。它包括如下文本框:

<TextBox Name="ConferenceNameTextBox"
                 Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
                 TextChanged="ConferenceNameTextBox_TextChanged"></TextBox>

文本框的 DataContext 是在 GridView 的 SelectionChanged 事件处理程序中以编程方式设置的:

ConferenceNameTextBox.DataContext = (Conference)ConferencesGridView.SelectedItem;

现在,在文本框的 TextChanged 事件处理程序中,以下代码行修改了 GridView 中选定项的属性(我知道使用 TextChanged 代替 LostFocus 会影响性能,但我会解决在我得到基本概念之后):

((Conference)ConferencesGridView.SelectedItem).Name = ConferenceNameTextBox.Text;

所以,在运行时,我会在 GridView 中选择不同的项目。那里没有问题;文本框的值会相应更新,显示当前选中的 GridView 项的名称值。

我更改了文本框中的文本,并且该文本成功更新了 GridView 用作源的项目。我通过在 GridView 中选择不同的项目,然后返回选择已编辑的项目,以及导航到框架内的不同 XAML 页面,然后返回到它被编辑的页面来验证这一点。编辑后的值被保留。

但是,当文本框的文本值更新时,GridView 的项目模板中显示的文本不会更新。 GridView 仅在重新加载 XAML 页面时更新(导航离开然后返回到它所在的框架中)。

我通过研究发现 ObservableCollection 足以从源中添加和删除项目(实际上这样做确实会更新 GridView),但这不足以更改源中列表项的属性.

我看到在源对象(在本例中为会议对象)上实现 INotifyPropertyChanged 是必要的。我已经这样做了。我还阅读了有关需要将文本框双向绑定到数据源的信息。我也试过了,没有成功:

public class Conference : INotifyPropertyChanged
{
    public string Name { get; set; }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

在 ASP.NET 中,我记得在编辑数据源中的数据后调用 GridView.DataBind(),这会刷新 GridView。不过,XAML 中似乎没有等价物。

我猜测缺少某些东西,或者我没有正确的组件组合。综上所述:

当文本框(位于 GridView 外部,用于编辑 GridView 中所选项目的 Name 属性)值时,如何获取 GridView 显示的项目(包括显示项目的 Name 属性)进行更新变化?

【问题讨论】:

  • 您可以尝试重新加载源代码吗?即,以编程方式将源设置为空,然后返回正确的源。这可能有点草率,但我相信这可能是最简单的解决方法。
  • 这是一个更普遍的问题,可能无法解决您的问题,但是...您应该避免使用 EventHandlers,尤其是当 - 在这种情况下 - 您可以在您已经绑定到的属性。此外,您可以考虑将SelectedItem 属性绑定到代码中的单独属性,然后绑定到该属性而不是依赖于数据上下文,而不是以编程方式更改数据上下文。这至少会让你的代码更容易预测/更容易阅读。
  • 我尝试以编程方式设置源,但这会破坏结果。 @SteffenWinkler,你能举个例子来说明你在说什么吗?我想我明白你的意思是:在 XAML 页面上创建一个属性,该属性绑定到(并因此填充)gridview 中当前选定的项目,然后将文本框绑定到那个…但我不是确定如何去做。
  • 您将SelectionChanged="ConferencesGridView_SelectionChanged" 替换为SelectedItem={Binding SelectedConference, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged},然后将private Conference selectedConference; public Conference SelectedConference{get{return selectedConference;}set{selectedConference=value;this.PropertyChanged();} 添加到包含您的数据网格绑定到的Conference 对象集合的类中。
  • 谢谢!我进行了建议的更改......但它并没有解决问题,并且它破坏了文本框和正在工作的内存对象之间的连接。不过,在事件上使用绑定的想法是有道理的。

标签: c# xaml gridview data-binding


【解决方案1】:

您可以使用ObservableCollection 例如 -

ObservableCollection<ClassName> DataList = new ObservableCollection<ClassName>(); //Declaration
gridName.ItemsSource=DataList;

它对我有用... 谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多