列表的wpf应用程序中的INotifyPropertyChanged

gopyfrb3  于 2022-11-26  发布在  其他
关注(0)|答案(1)|浏览(156)

问题

我想在应用程序中的对象列表发生更改时刷新wpf视图,但在我更改值时它不会注册INotifyChanged方法。
"我所尝试的"
我去了多个不同的stackoverflow页面,都遇到了同样的问题,但我没有让它正常工作。它不会注册列表中对象的变化。

我的代码

下面是WPF应用程序主窗口的代码,在其中单击最后一个按钮,我将更改列表中某个对象的XLocation值。

public partial class MainWindow : Window
{
    private string filePathArtist { get; set; }
    private string filePathGrid { get; set; }
    public Game.Game  Game { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        filePathGrid = String.Empty;
        filePathArtist = String.Empty;
    }

    private void BtnOpen_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        bool? res = openFileDialog.ShowDialog();
        if (res == true)
        {
            string filepathgrid = openFileDialog.FileName;
            filePathGrid = filepathgrid;
            GridTextBox.Text = filepathgrid;

        }

       
    }

    private void PickArtistBtn_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        bool? res = openFileDialog.ShowDialog();
        if (res == true)
        {
            string filepathartist = openFileDialog.FileName;
            filePathArtist = filepathartist;
            ArtistTextBox.Text = filepathartist;

        }

    }

    private void CreateGridBtn_Click(object sender, RoutedEventArgs e)
    {
        Game = new Game.Game(filePathGrid, filePathArtist);
        this.DataContext = Game;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Game.Artists[0].XLocation = 30;
    }
}

下一个代码是Game类,其中实现了艺术家列表上的INotfyPropertyChanged。

public class Game : INotifyPropertyChanged
{
    public List<Artist> _artists;

    public List<Artist> Artists
    {
        get
        {
            return _artists;
        }
        set
        {
            _artists = value;
            OnPropertyChanged("Artists");
        }
    }

    public List<ITile> Tiles { get; set; }

    public Game()
    {

    }
    public Game(string graphPath, string artistPath)
    {
        IDataParser graphParser = DataFactory.DataFactory.Instance.CreateParser(graphPath);
        IDataParser artistParser = DataFactory.DataFactory.Instance.CreateParser(artistPath);
        Tiles = graphParser.ParseGridData(graphPath);
        Artists = artistParser.ParseArtistData(artistPath);
        Test = "new Game";
    }

    public string Test { get; set; } = "t";

    public event PropertyChangedEventHandler? PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我还在艺术家类中添加了INotifyPropertyChanged

public class Artist : INotifyPropertyChanged
{
    private float _xLocation;
    private float _yLocation;
    private int _xVelocity;
    private int _yVelocity;
    public float XLocation
    {
        get => _xLocation;
        set
        {
            _xLocation = value;
            OnPropertyChanged("XLocation");
        }
    }
    public float ConvertedXLoc
    {
        get => XLocation * (float)3.75;
        set { }
    }

    public float YLocation
    {
        get => _yLocation;
        set
        {
            _yLocation = value;
            OnPropertyChanged("YLocation");
           
        }
    }

    public float ConvertedYLoc
    {
        get => YLocation * (float)3.75;
        set { }
    }

    public int XVelocity
    {
        get => _xVelocity;
        set
        {
            _xVelocity = value;
        }
    }

    public int YVelocity
    {
        get => _yVelocity;
        set
        {
            _yVelocity = value;
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

下面是将对象绑定到wpf UI的Xaml代码。

<Window x:Class="BroadwayBoogie.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:game="clr-namespace:BroadwayBoogie.Game"
    mc:Ignorable="d"
    Title="MainWindow" Height="900" Width="900"
    >
<Window.DataContext>
    <game:Game/>
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="201*"/>
        <ColumnDefinition Width="199*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="21*"/>
        <RowDefinition Height="401*"/>
        <RowDefinition Height="20*"/>
    </Grid.RowDefinitions>
    <Button x:Name="BtnOpen" Content="Pick Grid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="BtnOpen_Click"/>
    <TextBox x:Name="GridTextBox" HorizontalAlignment="Center" TextWrapping="NoWrap" VerticalAlignment="Center" Width="266" />
    <Button x:Name="PickArtistBtn" Content="Pick Artist" HorizontalAlignment="Left" Margin="356,0,0,0" VerticalAlignment="Center" Click="PickArtistBtn_Click" RenderTransformOrigin="-0.135,0.647"/>
    <TextBox x:Name="ArtistTextBox" HorizontalAlignment="Left" Margin="30,14,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="231" Grid.Column="1"/>
    <Button x:Name="CreateGridBtn" Grid.Column="1" Content="Create Grid" HorizontalAlignment="Left" Margin="311,14,0,0" VerticalAlignment="Top" Click="CreateGridBtn_Click"/>

    <Canvas Width="800" Height="800" Grid.ColumnSpan="2" Margin="49,15,51,27" Grid.Row="1" Background="DarkSeaGreen" Grid.RowSpan="2">
        <ItemsControl Name="tilesItemsControl" ItemsSource="{Binding Tiles}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
                        <Rectangle
                        Width="15"
                        Height="15"
                        Fill="{Binding Color}"
                        Canvas.Left ="{Binding ConvertedXLoc}"
                        Canvas.Top="{Binding ConvertedYLoc}" />
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <ItemsControl Name="ArtistItemsControl" ItemsSource="{Binding Artists}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
                        <Rectangle
                            Width="3.75"
                            Height="3.75"
                            Fill="Black"
                            Canvas.Left ="{Binding ConvertedXLoc}"
                            Canvas.Top="{Binding ConvertedYLoc}" />
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Canvas>
    <Grid/>
    <Button Content="Button" HorizontalAlignment="Left" Margin="4,0,0,0" Grid.Row="2" VerticalAlignment="Center" Click="Button_Click"/>


</Grid>

因此,按下我为测试目的而添加的按钮,它会更改List中的一个值,然后PropertyChanged方法应该会检测到它,但它没有检测到它,它只是跳过它。

问题

所以我的基本问题是,我如何从艺术家列表之外的对象中检测到属性的变化。

hpxqektj

hpxqektj1#

OnPropertyChanged只会在属性本身变更时执行。清单中的新项目不是属性变更。这就是为何不会发生更新的原因。
ObservableCollection实现了一个额外的INotifyCollectionChanged,使UI能够对列表中的更改项做出React。

相关问题