开发者

Observablecollection<T> in Listbox is not updating

开发者 https://www.devze.com 2023-04-08 02:46 出处:网络
I have a Silverlight Listbox bound to Observablecollection which shows up fine (first time) but when I try to update it through the code behind, the change does not reflect in UI. I have used MVVM pat

I have a Silverlight Listbox bound to Observablecollection which shows up fine (first time) but when I try to update it through the code behind, the change does not reflect in UI. I have used MVVM pattern . Pl have a look and at view and viewmodel.

<UserControl x:Class="GridOperations.MainPage"
    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:GridOperations.ViewModel"
    mc:Ignorable="d"
    d:DesignHeight="700" d:DesignWidth="700">
    <UserControl.DataContext>
        <local:ShowUserListViewModel/>
    </UserControl.DataContext>
    <UserControl.Resources>
        <local:ShowUserListViewModel x:Key="viewModelKey"/>
    </UserControl.Resourc开发者_C百科es>

    <Grid x:Name="LayoutRoot" Background="White">

        <ListBox VerticalAlignment="Top" Margin="0,20,0,0" x:Name="lstBox" ItemsSource="{Binding UserList}" Width="700" Height="150" Background="AliceBlue">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="300"/>
                            <ColumnDefinition Width="100"/>
                            <ColumnDefinition Width="100"/>
                            <ColumnDefinition Width="100"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Margin="30,0,0,0" Text="{Binding UserId}" HorizontalAlignment="Left"/>
                        <TextBlock Margin="30,0,0,0" Text="{Binding Path=UserName, Mode=TwoWay}" Grid.Column="1" HorizontalAlignment="Left"/>
                        <Button Margin="30,0,0,0" Grid.Column="2" Content="Edit" Height="20" HorizontalAlignment="Left" Command="{Binding Source={StaticResource viewModelKey}, Path=UpdateUserCommand}" />
                        <Button Margin="10,0,0,0" Grid.Column="3" Content="Del" Height="20" HorizontalAlignment="Left" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
</UserControl>


    public class ShowUserListViewModel : INotifyPropertyChanged
        {
            public ShowUserListViewModel()
            {
                mUserList = new ObservableCollection<User>();
                mUserList.Add(new User() { UserId = Guid.NewGuid().ToString(), UserName = "testuser1", IsAdmin = true });
                mUserList.Add(new User() { UserId = Guid.NewGuid().ToString(), UserName = "testuser2", IsAdmin = true });

                this.UpdateUserCommand = new DelegateCommand(this.UpdateUser);

            }

            public ICommand UpdateUserCommand { get; private set; }

            private ObservableCollection<User> mUserList;
            public ObservableCollection<User> UserList
            {
                get
                {
                    return mUserList;
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void UpdateUser()
            {
                this.UserList.Add(new User() { UserId = Guid.NewGuid().ToString(), UserName = "test", IsAdmin = false });            
            }
        }


Firstly, you should avoid putting a collection property writable. IE, replace this code :

    private ObservableCollection<User> mUsers = new ObservableCollection<User>();
    public ObservableCollection<User> Users
    {
        get
        {
            return mUsers;
        }
        set
        {
            mUsers = value;
            RaisePropertyChangedEvent("Users");
        }
    }

by this code :

    private ObservableCollection<User> mUsers = new ObservableCollection<User>();
    public ObservableCollection<User> Users
    {
        get
        {
            return mUsers;
        }

    }

Then, when you add an item to the collection, you don't have to tell the collection has changed (the collection property hasn't changed in itself), but it's the responsibility of the collection itself (via INotifyCollectionChanged) :

So, the "onclick" method can be simply like this:

 private void OnClick(User userInstanceToEdit)
    {
        this.Users.Add(new User() { UserId = Guid.NewGuid().ToString(), UserName = "test", IsAdmin = false });         

    }

Finally, I would replace the ListBox.ItemsSource declaration with this one, as two ways is not required :

 <ListBox x:Name="lstBox" ItemsSource="{Binding Users}" 


Got a hint from this post Stackoverflow

Basically I need to use Datacontext with Listbox control (even after setting the Datacontext at UserControl level). The only line that required change is:

<ListBox x:Name="lstBox" ItemsSource="{Binding Users}" DataContext="{StaticResource viewModelKey}"  Width="750" Background="AliceBlue">
0

精彩评论

暂无评论...
验证码 换一张
取 消