WPF ViewModel 更改不更新 Listview

问题描述 投票:0回答:3

当按下获取数据按钮时,UserControllers 中的 User_List 发生更改,但主窗口中的列表视图未更新。我使用数据库作为 EntityFramework6.0 我分享给你 UserController.cs(Viewmodel),Users.cs,MainWindow.cs,MainWindow.xaml 我该如何解决这个问题?

MainWindows.cs

public partial class MainWindow : Window ,INotifyPropertyChanged

{
    ViewModels.UsersController controller1;

    public ObservableCollection<Users> user_List;

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public ObservableCollection<Users> User_List
    {
        get { return user_List; }
        set {lst1.ItemsSource=user_List = value;OnPropertyChanged("User_List"); }
    }

    public MainWindow()
    {
        InitializeComponent();
        controller1 = new ViewModels.UsersController();
        this.DataContext = controller1;
    }
   
   
    private void Fetch_Data_Button_Click(object sender, RoutedEventArgs e)
    {
        ViewModels.UsersController controller = new ViewModels.UsersController();
        controller.Increase();
        lst1.UpdateLayout();
    }
}

主窗口.xaml

Window x:Class="MSSQLServer.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:local="clr-namespace:MSSQLServer"
        xmlns:vw="clr-namespace:MSSQLServer.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" >
    <Window.DataContext>
        <vw:UsersController/>
    </Window.DataContext>
    <Grid>
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button x:Name="Fetch_Data_Button" Click="Fetch_Data_Button_Click" Content="Fetch Data" Width="150" Height="40" FontSize="18" Margin="10,10"></Button>
            </StackPanel>
            <ListView x:Name="lst1" HorizontalAlignment="Center" VerticalAlignment="Center" Height="300" Width="600" ItemsSource="{Binding User_List,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                <ListView.View>
                    <GridView>
                        <GridView.Columns>
                            <GridViewColumn Header="Id" DisplayMemberBinding="{Binding id,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="50"></GridViewColumn>
                            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="120"></GridViewColumn>
                            <GridViewColumn Header="Surname" DisplayMemberBinding="{Binding surname,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="120"></GridViewColumn>
                            <GridViewColumn Header="Age" DisplayMemberBinding="{Binding age,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="120"></GridViewColumn>
                            <GridViewColumn Header="E-Mail" DisplayMemberBinding="{Binding email,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="120"></GridViewColumn>

                        </GridView.Columns>
                    </GridView>
                </ListView.View>
            </ListView>
           

        </StackPanel>
        
    </Grid>
</Window>

用户控制器.cs

public class UsersController :INotifyPropertyChanged
    {
        public ObservableCollection<Users> user_List;
        public ObservableCollection<Users> User_List
        {
            get { return user_List; }
            set { user_List = value;OnPropertyChanged("User_List"); }
        }
      
        public UsersController()
        {
            Increase();
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
       
       
        public void Increase()
        {
            Database1Entities entities = new Database1Entities();
            User_List = new ObservableCollection<Users>(entities.Users.ToList());
            
        }
    }

和Users.cs

public class Userss : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private int idd;
        public int id
        {
            get { return idd; }
            set { idd = value; OnPropertyChanged("id"); }
        }
        private string namee;
        public string name
        {
            get { return namee; }
            set { namee = value; OnPropertyChanged("name"); }
        }
        private string surnamee;
        public string surname
        {
            get { return surnamee; }
            set { surnamee = value; OnPropertyChanged("surname"); }
        }
        private int agee;
        public int age
        {
            get { return agee; }
            set { agee = value; OnPropertyChanged("age"); }
        }
        private string emaill;
        public string email
        {
            get { return emaill; }
            set { emaill = value; OnPropertyChanged("email"); }
        }

    }
c# wpf visual-studio mvvm data-binding
3个回答
2
投票

看看我的最新答案:C# wpf listview Binding Problem with observable collection

这是至少在开始时如何使用列表视图/树视图/网格视图的基本示例。如果你尝试它,那么你会将大部分代码移至 ViewModel 部分,但随后你将搜索命令和它们之间的交互(棱镜可能没问题 - 我的意思是事件聚合,不要依赖注入太快)。

您的一个类名为 UsersController。当您切换到 WPF 时,请记住 MVC 模式已不再存在,并且大部分位于 ViewModel 中的某个位置,因此它更像 UserViewModel 或 UsersViewModel。如果我没理解错的话,那么我告诉你,从经典的 MVC(各种实现)切换到某种正确的、令人愉快的 MVVM 是很困难的。

我提供的URL缺少一件主要的事情,那就是标准的ViewModelWrapper,通常称为ViewModelBase或BaseViewModel,你自己称呼它。

它已经成型(不过它应该是我第一篇文章的一部分):

namespace MyNamespace.ViewModel
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

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

        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
                return false;
            storage = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }

    }
}

0
投票

首先,您应该删除以下 XAML,因为您是以编程方式设置

DataContext

<Window.DataContext>
    <vw:UsersController/>
</Window.DataContext>

其次,您应该调用

Increase()
的数据绑定实例的
UsersController
方法:

private void Fetch_Data_Button_Click(object sender, RoutedEventArgs e)
{
    controller1.Increase();
}

-1
投票

这是在 BaseViewModel 中执行此操作的另一种方法:

public event PropertyChangedEventHandler PropertyChanged;

protected bool SetProperty<T>(ref T fieldReference, T newValue, Expression<Func<T>> property)
{
    bool valueIsDifferent = false;
    if (!object.Equals(fieldReference, newValue))
    {
        valueIsDifferent = true;
        fieldReference = newValue;

        var memberExpression = property.Body as MemberExpression;
        OnPropertyChanged(memberExpression.Member.Name);
    }
    return valueIsDifferent;
}

protected void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是如何在视图模型中使用它

    private int _myProperty;
    public int MyProperty
    {
        get
        {
            return _myProperty;
        }
        set
        {
            SetProperty(ref _myProperty, value, () => MyProperty);
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.