C# WPF列表框数据绑定

C# WPF列表框数据绑定,c#,wpf,xaml,listbox,C#,Wpf,Xaml,Listbox,这里是WPF的新成员。正在构建的应用程序有一个从数据库中提取的用户列表,显示在“用户”窗口中,可从“主”窗口导航。列表似乎被转移到代码隐藏中,但用户列表没有显示在“用户”窗口列表框中。有人知道为什么没有显示吗?非常感谢 “主”窗口定向: UsersViewModel Usersvm = new UsersViewModel(); Usersvm.Users = new List<UserViewModel>(); DbEntities db = new DbEntities(); v

这里是WPF的新成员。正在构建的应用程序有一个从数据库中提取的用户列表,显示在“用户”窗口中,可从“主”窗口导航。列表似乎被转移到代码隐藏中,但用户列表没有显示在“用户”窗口列表框中。有人知道为什么没有显示吗?非常感谢

“主”窗口定向:

UsersViewModel Usersvm = new UsersViewModel();
Usersvm.Users = new List<UserViewModel>();
DbEntities db = new DbEntities();
var pulledUsers = db.uspGetUsers().ToList();
foreach (var result in pulledUsers)
{
    var pulledUser = new UserViewModel
    {
        FirstName = result.FirstName,
        LastName = result.LastName,
        EMail = result.Email,
        UserID = result.UserID,
        Position = result.Position,
        EndDate = result.EndDate,
    };
    Usersvm.Users.Add(pulledUser);
}
new UsersWindow(Usersvm).Show();
UsersWindow.xaml:

<Window x:Class="DbEntities.UsersWindow"
    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:DbEntities"
    mc:Ignorable="d"
    Title="UsersWindow" Height="Auto" Width="900">
    <Window.Resources>
        <Style x:Key="borderBase" TargetType="Border">
            <Setter Property="BorderBrush" Value="Black" />
            <Setter Property="BorderThickness" Value="1" />
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBlock x:Name="textBlock" Height="21" Margin="0,0,161,0" TextWrapping="Wrap" 
            Text="Users Page" VerticalAlignment="Top" RenderTransformOrigin="1.022,0.409" HorizontalAlignment="Right" Width="344"/>
        <Grid>
            <Grid Grid.IsSharedSizeScope="True">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="151*" />
                        <ColumnDefinition Width="95*" />
                        <ColumnDefinition Width="110*" />
                        <ColumnDefinition Width="351*" />
                        <ColumnDefinition Width="75*" />
                        <ColumnDefinition Width="110*" />
                    </Grid.ColumnDefinitions>
                    <Border Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" Text="Last Name" />
                    </Border>
                    <Border Grid.Column="1" Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" Text="First Name" />
                    </Border>
                    <Border Grid.Column="2" Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" Text="Position" />
                    </Border>
                    <Border Grid.Column="3" Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" Text="Email" />
                    </Border>
                    <Border Grid.Column="4" Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" Text="End Date" />
                    </Border>
                    <Border Grid.Column="5" Style="{StaticResource borderBase}">
                        <TextBlock HorizontalAlignment="Center" />
                    </Border>
                    <ListBox x:Name="listboxUsers" HorizontalAlignment="Center" Height="Auto" Margin="3,25,0,0" VerticalAlignment="Top" Width="889"
                    ItemsSource="{Binding Users}" Grid.ColumnSpan="6">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition SharedSizeGroup="LastNameColumn" />
                                    </Grid.ColumnDefinitions>
                                    <Border Style="{StaticResource borderBase}">
                                        <TextBlock Text="{Binding LastName}"/>
                                    </Border>
                                    <Border Style="{StaticResource borderBase}">
                                        <TextBlock Text="{Binding FirstName}"/>
                                    </Border>
                                    <Border Style="{StaticResource borderBase}">
                                        <TextBlock Text="{Binding Position}"/>
                                    </Border>
                                    <Border Style="{StaticResource borderBase}">
                                        <TextBlock Text="{Binding Email}"/>
                                    </Border>
                                    <Border Style="{StaticResource borderBase}">
                                        <TextBlock Text="{Binding EndDate}"/>
                                    </Border>
                                    <Border Style="{StaticResource borderBase}">
                                        <Button Content="Edit" x:Name="editButton" Click="editButton_Click"/>
                                    </Border>
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </Grid>
            </Grid>
        </Grid>
    </StackPanel>
</Window>

最后是UsersViewModel,其中包含用户联系信息的列表:

public partial class UsersViewModel : Window
{
    public List<UserViewModel> Users { get; set; }
}
public分部类UsersViewModel:窗口
{
公共列表用户{get;set;}
}
编辑(已解决):
Ed Plunkett的评论和回答直接解决了最初的列表框问题,并将该输入与ThyArtIsCode结合使用,这一切都是由Monty巧妙地呈现的,整个过程更加优雅。感谢所有回复的人-这里有很多很棒的学习材料。

我发现有两件事不对

首先,您的ViewModel将继承窗口。如果没有什么特别的原因,就把它扔掉。如果要通知UI对集合所做的更改(理想情况下,集合应该是视图模型的一部分),请使视图模型继承INotifyPropertyChanged

您还在此处绑定到列表框:

ItemsSource="{Binding Users}"
并在此处再次设置ItemsSource:

listboxUsers.ItemsSource = uvm.Users;
糟糕!如果您使用XAML进行绑定,则绝对不需要再次设置ItemsSource。需要修改集合吗?直接对集合执行此操作

另外,由于您是WPF的新手,我想我应该添加一些建议,这些建议在我第一次开始学习时对我有所帮助:

  • 如果您希望事情进展更快,请将
    IsAsync=True
    添加到您的列表框绑定中。这将启用异步绑定(我知道这很神奇)
  • 虚拟化列表框中的垃圾(只需将以下内容添加到列表框中):

  • 还有最后一件事,尽管其他人建议使用ObservableCollection,但它在使用大数据时也会带来性能上的损失。即使您不打算拥有大数据,使用BindingList也总是比较安全的。事实上,在处理较小的数据集时,ObservableCollection占上风


    它们的速度更快,并且与OC有许多相似的特性。

    我发现有两件事不对

    首先,您的ViewModel将继承窗口。如果没有什么特别的原因,就把它扔掉。如果要通知UI对集合所做的更改(理想情况下,集合应该是视图模型的一部分),请使视图模型继承INotifyPropertyChanged

    您还在此处绑定到列表框:

    ItemsSource="{Binding Users}"
    
    并在此处再次设置ItemsSource:

    listboxUsers.ItemsSource = uvm.Users;
    
    糟糕!如果您使用XAML进行绑定,则绝对不需要再次设置ItemsSource。需要修改集合吗?直接对集合执行此操作

    另外,由于您是WPF的新手,我想我应该添加一些建议,这些建议在我第一次开始学习时对我有所帮助:

  • 如果您希望事情进展更快,请将
    IsAsync=True
    添加到您的列表框绑定中。这将启用异步绑定(我知道这很神奇)
  • 虚拟化列表框中的垃圾(只需将以下内容添加到列表框中):

  • 还有最后一件事,尽管其他人建议使用ObservableCollection,但它在使用大数据时也会带来性能上的损失。即使您不打算拥有大数据,使用BindingList也总是比较安全的。事实上,在处理较小的数据集时,ObservableCollection占上风

    它们的速度更快,并且与OC有许多相似的属性。

    好的,试试这个

    视图模型

    class Base_ViewModel : INotifyPropertyChanged
    {
        public RelayCommand<UserViewModel> editButton_Click_Command { get; set; }
    
        public Base_ViewModel()
        {
            editButton_Click_Command = new RelayCommand<UserViewModel>(OneditButton_Click_Command);
    
            this.Users = new ObservableCollection<UserViewModel>();
    
            this.Users.Add(new UserViewModel() { FirstName = "John", LastName = "Doe", EMail = "JohnDoe@yahoo.com", EndDate = "02-01-2016", Position = "Developer", UserID = "AADD543" });
        }
    
        private ObservableCollection<UserViewModel> _Users;
        public ObservableCollection<UserViewModel> Users
        {
            get { return _Users; }
            set { _Users = value; NotifyPropertyChanged("Users"); }
        }
    
        private void OneditButton_Click_Command(UserViewModel obj)
        { // put a break-point here and you will see the data you want to Edit in obj
    
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
    
    XAML

    设置窗口x:Name

    <Window x:Name="Base_V"......
    
    当用户为空记录选择编辑按钮时,实际上他们只是在填写一个空记录,一旦他们填写完,请确保添加另一个空记录以在数据网格中生成一个新的(空行)…

    确定尝试此操作

    视图模型

    class Base_ViewModel : INotifyPropertyChanged
    {
        public RelayCommand<UserViewModel> editButton_Click_Command { get; set; }
    
        public Base_ViewModel()
        {
            editButton_Click_Command = new RelayCommand<UserViewModel>(OneditButton_Click_Command);
    
            this.Users = new ObservableCollection<UserViewModel>();
    
            this.Users.Add(new UserViewModel() { FirstName = "John", LastName = "Doe", EMail = "JohnDoe@yahoo.com", EndDate = "02-01-2016", Position = "Developer", UserID = "AADD543" });
        }
    
        private ObservableCollection<UserViewModel> _Users;
        public ObservableCollection<UserViewModel> Users
        {
            get { return _Users; }
            set { _Users = value; NotifyPropertyChanged("Users"); }
        }
    
        private void OneditButton_Click_Command(UserViewModel obj)
        { // put a break-point here and you will see the data you want to Edit in obj
    
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
    
    XAML

    设置窗口x:Name

    <Window x:Name="Base_V"......
    
    当用户为空记录选择编辑按钮时,实际上他们只是在填写
    <Grid>
        <DataGrid Name="DataGrid1" ItemsSource="{Binding Users}">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Command="{Binding DataContext.editButton_Click_Command, ElementName=Base_V}" CommandParameter="{Binding}">Edit</Button>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
    </Window>
    
            this.Users.Add(new UserViewModel() { FirstName = "John", LastName = "Doe", EMail = "JohnDoe@yahoo.com", EndDate = "02-01-2016", Position = "Developer", UserID = "AADD543" });
            this.Users.Add(new UserViewModel() { FirstName = "Fred", LastName = "Doe", EMail = "FredDoe@yahoo.com", EndDate = "02-01-2016", Position = "Developer", UserID = "AADD543" });
            // empty record to allow the use to Add a new record
            this.Users.Add(new UserViewModel());
    
    private ObservableCollection<UserViewModel> _users =
        new ObservableCollection<UserViewModel>();
    ObservableCollection<UserViewModel> Users {
        get { return _users; }
        set {
            _users = value;
            //  Implementations of this are everywhere on Google, very simple. 
            OnPropertyChanged("Users");
            //  Or in C#6
            //PropertyChanged?.Invoke(new PropertyChangedEventArgs(nameof(Users)));
        }
    }
    
    public partial class UsersWindow : Window
    {
        public UsersWindow(UsersViewModel uvm)
        {
            InitializeComponent();
    
            var vm = new UsersViewModel();
            //  initialize vm if needed
            DataContext = vm;
        }
    }