【问题标题】:ListView items do not displayListView 项目不显示
【发布时间】:2018-06-10 18:35:09
【问题描述】:

我有一个相当简单的ListViewGridView 风格。单元格绑定到 ObservableCollection 元素的某些属性。我不知道为什么 thaey 不显示。我正在考虑在集合包含的元素类中实现INotifyPropertyChanged,但是一旦构造了一个元素并将其添加到集合中,它就永远不会改变,所以它应该可以正常工作。

C#:

public ObservableCollection<SceneElement> SceneObjects { get; set; }
...
SceneObjects.Add(new Camera());
SceneObjects.Add(new Cuboid(20, 30, 40));

CameraCuboid 都继承自 SceneObject (SceneObject Figure Cuboid 和 SceneObject Camera)

XAML:

<ListView Grid.Column="2" Margin="5"
                      ItemsSource="{Binding }"
                      DataContext="{Binding SceneObjects}"
                      ScrollViewer.CanContentScroll="True">
                <ListView.Resources>
                    <GridView x:Key="StyleOne">
                        <GridViewColumn Header="Type" >
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="1" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Position" >
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="X: " />
                                        <TextBlock Text="{Binding Position.X, RelativeSource={RelativeSource Mode=FindAncestor}}" />
                                        <TextBlock Text=" Y: " />
                                        <TextBlock Text="{Binding Position.Y}" />
                                        <TextBlock Text=" Z: " />
                                        <TextBlock Text="{Binding Position.Z}" />
                                    </StackPanel>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.Resources>
                <ListView.Style>
                    <Style TargetType="ListView">
                        <Setter Property="View" Value="{StaticResource StyleOne}" />
                    </Style>
                </ListView.Style>
            </ListView>

Position 属性在抽象 SceneElement 类中定义。 PositionXYZ 也是属性。

编辑

这已经解决了问题:

private ObservableCollection<SceneElement> sceneObjects;
    public ObservableCollection<SceneElement> SceneObjects
    {
        get
        {
            return sceneObjects;
        }
        set
        {
            sceneObjects = value;
            NotifyPropertyChanged("SceneObjects");
        }
    }

谁能解释为什么这是必要的?到目前为止,我已经使用了ObservableCollection 严重的时间,它总是在没有通知的情况下工作。

【问题讨论】:

  • 您将ObservableCollection 设置为DataContext?我会将包含 ObservableCollection 的 VM 设置为上下文,然后将 ItemSource 绑定到 SceneObjects?
  • 在我看来,将ItemSource 绑定到SceneObjectsDataContext 到VM 是一回事。当您将DataContext 绑定到ObservableCollection,然后将ItemSource 绑定到{Binding} 时,它将绑定到此集合包含的元素。我过去做过,效果很好。
  • 很好学的东西。谢谢
  • 您仍然需要通知正在更改的属性。因此 PropertyChanged 事件。 Observable 集合将通知更改,但 UI 不知道最初为 null 的属性现在包含项目。跳这个有道理。
  • 这听起来像是一种代码隐藏方法。你应该避开这一点。它会为您省去很多麻烦。

标签: wpf xaml listview binding


【解决方案1】:

您的应用程序未显示有关集合的信息的原因是 UI 不知道任何更改。
使用ObservableCollection 并不能保证如果所述集合在使用之前未初始化,则将显示结果。因为它是 ViewModel 上的一个普通属性,所以它需要通知所述对象,在这种情况下,ObservableCollection 已更改,但不是在集合内的感知项中。
这是因为NOTSceneObjects 引发PropertyChanged 事件,这对于使用BidningWPF 应用程序至关重要。

【讨论】:

    【解决方案2】:

    在 wpf 系统尝试创建绑定时,您的 observablecollection 为空,正如上面的 xamimax 所说。

    在您的构造函数中实例化您的 observablecollection,稍后您可以添加项目,它们就会出现。

    例如,因为我首先实例化了 observable 集合,然后在 5 秒后添加了项目,所以下面的代码有效。

     public MainWindow()
     {
         InitializeComponent();
         this.SceneObjects = new ObservableCollection<MyClass>();
         Task.Delay(5000).ContinueWith((old) =>
         {
             this.Dispatcher.Invoke(() =>
             {
                 this.sceneObjects.Add(new MyClass("name"));
                 this.sceneObjects.Add(new MyClass("name"));
             });
         });
    
         this.DataContext = this;
     }
    

    这是一个不起作用的示例,因为我在 wpf 系统尝试绑定到它后 5 秒实例化了 observable 集合:

    public MainWindow()
    {
            InitializeComponent();
            Task.Delay(5000).ContinueWith((old) => { this.SceneObjects = new ObservableCollection<MyClass> { new MyClass("name"), new MyClass("name") }; });
    
            this.DataContext = this;
    }
    

    正如您已经意识到的那样,您可以抛出 propchanged 以使 wpf 系统显示这些项目,但我认为您应该更早地实例化 observablecollection,这样您就不需要稍后再抛出 propchanged。

    【讨论】:

    • “throw propchanged”是什么意思?
    • NotifyPropertyChanged("SceneObjects");
    • 你明白什么都不是扔东西吗?
    • “扔东西”是什么意思? “任何东西”是您开发的例外吗?什么是“无”?你能提供你的nothing.cs吗?
    • 如果您在理解引发异常和引发事件之间的区别时遇到困难,您应该阅读两者。那里有很多好的 C# 引物。当我们在这里时,您也不应该推荐DataContext = this;
    猜你喜欢
    • 1970-01-01
    • 2021-05-13
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多