2
\$\begingroup\$

Please, help improve following code. I have list of users, item of the list has buttons remove (remove user from list) and profile (navigate to user profile). I use MVVM pattern and GalaSoft MVVM Light Libraries.

Model

   public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

ViewModel

UsersViewModel

public class UsersViewModel : INotifyPropertyChanged
{
    private ObservableCollection<UserViewModel> _users;
    public ObservableCollection<UserViewModel> Users
    {
        get { return _users; }
        set
        {
            _users = value;
            NotifyPropertyChanged("Users");
        }
    }

    public UsersViewModel()
    {
        Users = new ObservableCollection<UserViewModel>();
        Messenger.Default.Register<UserViewModel>(this, (user) =>
            {
                Users.Remove(user);
            });
    }

    public void Load()
    {
        //get data from web service    
        //....mock object to compile code

        var mockUsers = new List<User>()
        {
            new User()
            {
                Id = 0,
                Name = "User0"
            },
            new User()
            {
                Id = 0,
                Name = "User1"
            },
            new User()
            {
                Id = 0,
                Name = "User2"
            }
        };

        foreach (var item in mockUsers)
        {
            Users.Add(new UserViewModel()
            {
                Model = item,
            });
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

UserViewModel

public class UserViewModel
    {
        public User Model {get; set;}

        private ICommand _toProfileCmd;
        public ICommand ToProfileCmd 
        {
            get { return _toProfileCmd; }
            set
            {
                _toProfileCmd = value;
            }
        }

        private ICommand _removeCmd;
        public ICommand RemoveCmd
        {
            get { return _removeCmd; }
            set
            {
                _removeCmd = value;
            }
        }

        public UserViewModel()
        {
            _toProfileCmd = new DelegateCommand(ToProfile);
            _removeCmd = new DelegateCommand(Remove);
        }

        private void ToProfile(object p)
        {
            PhoneApplicationService.Current.State["user"] = this.Model;
            PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame;
            root.Navigate(new Uri("/View/Profile.xaml", UriKind.Relative));

        }

        private void Remove(object p)
        {
            Messenger.Default.Send<UserViewModel, UsersViewModel>(this);
        }    

View XAML

<Grid x:Name="LayoutRoot" Background="Transparent">
    <phone:LongListSelector ItemsSource="{Binding Users}">
        <phone:LongListSelector.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="15,10,0,10">                        
                    <TextBlock Text="{Binding Model.Name}" Style="{StaticResource PhoneTextTitle2Style}"/>
                    <StackPanel Orientation="Horizontal">
                        <Button Content="Profile" Command="{Binding ToProfileCmd}"/>
                        <Button Content="Remove" Command="{Binding RemoveCmd}"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </phone:LongListSelector.ItemTemplate>
    </phone:LongListSelector>
</Grid>

View .cs

public partial class MainPage : PhoneApplicationPage
    {
        UsersViewModel viewModel = new UsersViewModel();

        public MainPage()
        {
            InitializeComponent();
            this.DataContext = viewModel;
            viewModel.Load();
        }

    }

What could be improved?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ The method mentioned in your postscript is probably the right strategy, only partially because it will respond to all events that select an item. Your main strategy might work somewhat if you include a command parameter, but it's still going to be less normal. It is generally speaking a better idea to write code the way people expect to see it, for the future's sake. \$\endgroup\$ – Magus Jul 28 '14 at 23:10
1
\$\begingroup\$

Your code can use stricter access modifiers. For example, some of your properties look like they are not supposed to have public set accessor, yet they do. Commands can also be refactored to auto-properties. Apart from that your code looks pretty clean in my opinion.

INotifyPropertyChanged implementation should be moved to base class, unless that is the only view model you are going to have in your application.

As I am not very familiar with windows phone frameworks, I do not know what Messenger.Default is, but i assume that it is some kind of events aggregator. If it is the case, then it is probably a good idea to unregister your delegate at some point, to unsubscribe from events as you navigate to different view.

\$\endgroup\$
0
\$\begingroup\$

In advance to Nikita Brizhak answer.

You should move your RemoveCmd to your UsersViewModel because the List should handle Delete of here items to get the UserVM you can use the CommandParameter

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.