为了账号安全,请及时绑定邮箱和手机立即绑定

如何修复“对象引用未设置到对象的实例”。将事件绑定到使用 MVVM

如何修复“对象引用未设置到对象的实例”。将事件绑定到使用 MVVM

C#
ibeautiful 2022-11-22 15:43:35

我有一个 ListView,其中 ItemsSource 设置为一种 Movies 集合(带有 Movie 对象)。然后我在里面有一个 DataTemplate,其中包含一个 ComboBox 和一个 TextBlock。在 ComboBox 上,我将 Selected 项目绑定到 Movie 对象包含的(剧集的)进度。这里我使用的是普通的“绑定”方法。但是当我想将方法绑定到“DropDownClosed”事件时,问题就来了。这在使用 Code Behind 时工作正常,但使用 ViewModel 和 x:Bind 时它给我“对象引用未设置到对象的实例”。在构建我的应用程序时。


目标是绑定到 ViewModel 中的方法,而不是没有错误的代码隐藏。


当我取消“DropDownClosed”事件时,一切都很顺利。没有其他事件效果更好。


<ListView ItemsSource="{x:Bind ViewModel.MovieLibrary}">

    <ListView.ItemTemplate>

        <DataTemplate>

            <StackPanel Spacing="20" Orientation="Horizontal">

                <ComboBox SelectedItem="{Binding Progress}"

                                          ItemsSource="{Binding Media.Episodes, Converter={StaticResource NumberToArrayConverter}}"

                                          DropDownClosed="{x:Bind ViewModel.UpdateStuff}">

                </ComboBox>

                <TextBlock Text="{Binding Media.Title}" TextWrapping="Wrap" />

            </StackPanel>

        </DataTemplate>

    </ListView.ItemTemplate>

</ListView>

还有这个,但是如果它是空的,它的效果也一样糟糕,所以如果有必要(从视图模型来看),请 idk :


public void UpdateStuff(object sender, object e)

        {

            //blabla not important

        }

问题是我根本无法对任何属性使用 x:Bind。


查看完整描述

2 回答

?
蝴蝶刀刀

TA贡献1520条经验 获得超1个赞

要在 DataTemplate 中使用 x:Bind,您必须在 DataTemplate 中指定 x:DataType="local:Movie"。模板中 x:Bind 中的路径应与 Movie 对象相关。

“未设置对象引用”仅表示您尚未分配指针。也许 ViewModel 为 null 或 ViewModel.UpdateStuff 为 null。


查看完整回答
反对 回复 2022-11-22
?
12345678_0001

TA贡献1508条经验 获得超5个赞

我现在尝试通过一个小例子向您展示一个解决方案。你会看到有些事情发生了变化。我希望它仍然能满足您的需要:


    <ListView ItemsSource="{Binding MovieLibrary}">

        <ListView.ItemTemplate>

            <DataTemplate>

                <StackPanel Orientation="Horizontal">

                    <ComboBox  ItemsSource="{Binding Episodes}" 

                               SelectedItem="{Binding Progress}" >

                    </ComboBox>

                    <TextBlock Text="{Binding Title}" TextWrapping="Wrap" />

                </StackPanel>

            </DataTemplate>

        </ListView.ItemTemplate>

    </ListView>

这是一个示例视图模型:


public class MainWindowModel

{

    public MainWindowModel()

    {

        MovieLibrary = new ObservableCollection<Media>();


        //

        //Exmaple Fill

        //

        var m1 = new Media() { Title = "Breaking Bad", Episodes = new List<string> { "1", "2", "3", "4", "5", "6" } };

        var m2 = new Media() { Title = "The Big Bang Theory", Episodes = new List<string> { "1", "2", "3" } };

        m1.MediaChangedAction += OnMediaChanged;

        m2.MediaChangedAction += OnMediaChanged;

        MovieLibrary.Add(m1);

        MovieLibrary.Add(m2);

    }

    public ObservableCollection<Media> MovieLibrary { get; set; }


    private void OnMediaChanged(Media movie)

    {

        // do something

    }


}


public class Media

{

    public event Action<Media> MediaChangedAction;


    public Media()

    {

    }


    public string Title { get; set; }

    public List<string> Episodes { get; set; }



    private string _progress;

    public string Progress

    {

        get { return _progress; }

        set

        {

            _progress = value;

            MediaChangedAction?.Invoke(this);

        }

    }

}

你看我简化了一点(没有转换器等)。“事件”也被移动到视图模型。对我来说,优点是,它现在不依赖于视图来调用事件,它只是对视图模型很重要。因此,如果您制作不同的视图来显示媒体,它仍然可以正常工作。


我也远离了“双向”的东西,因为目前没有必要从视图模型发送到视图。如果需要,“媒体”将需要实施 INotifyPropertyChanged。


查看完整回答
反对 回复 2022-11-22
  • 2 回答
  • 0 关注
  • 16 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信