简体   繁体   English

ViewModels是否应该继承Xamarin.Forms中的其他ViewModels?

[英]Should ViewModels inherit other ViewModels in Xamarin.Forms?

Should ViewModels inherit other ViewModels ? ViewModels应该继承其他ViewModels吗?

I have a MerchandiserViewModel that contains the basic properties and database functions for a Merchandiser model.我有一个MerchandiserViewModel ,其中包含Merchandiser model 的基本属性和数据库函数。

The MerchandiserViewModel has a SelectedMerchandiser property that holds the selected Merchandiser from the ItemSelected in a ListView MerchandiserViewModel有一个SelectedMerchandiser属性,该属性保存从ListView中的ItemSelected中选择的Merchandiser

MerchandiserViewModel.cs MerchandiserViewModel.cs

public MerchandiserViewModel : INotifyPropertyChanged
{
    // Property to hold the selected Merchandiser
    // Generally I would make this static but then I can't bind the property
    public Merchandiser SelectedMerchandiser {get; set;}

    // Other logic...

}

The MerchandiserViewModel is instantiated as a Static Resource in App.xaml so that I only have one instance of the view model. MerchandiserViewModelApp.xaml中实例化为Static Resource ,因此我只有一个视图实例 model。

App.xaml App.xaml

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MobileApp.App"
             xmlns:ViewModels="clr-namespace:MobileApp.ViewModels">
    <Application.Resources>
        <ViewModels:MerchandiserViewModel x:Key="MerchandiserViewModel" />
        <ViewModels:MerchandiserProfileViewModel x:Key="MerchandiserProfileViewModel" />
    </Application.Resources>
</Application>

For each View related to a Merchandiser eg MerchandiserProfile , EditProfile etc. I create a new ViewModel and inherit the MerchandiserViewModel对于与 Merchandiser 相关的每个View ,例如MerchandiserProfileEditProfile等。我创建一个新的ViewModel并继承MerchandiserViewModel

MerchandiserProfileViewModel.cs inherits the MerchandiserViewModel MerchandiserProfileViewModel.cs继承 MerchandiserViewModel

public class MerchandiserProfileViewModel : MerchandiserViewModel
{
    // Logic Specific to the Merchandiser Profile View
}

The problem is... when I create a new [Page]ViewModel and inherit the "MerchandiserViewModel" I receive the following error message.问题是......当我创建一个新的[Page]ViewModel并继承“MerchandiserViewModel”时,我收到以下错误消息。

错误信息

I think this may be because a new instance of the MerchandiserViewModel is created so I am not referencing the initial SelectedMerchandiser property.我认为这可能是因为创建了MerchandiserViewModel的新实例,所以我没有引用初始SelectedMerchandiser属性。

This makes me think that inheriting ViewModels isn't a good idea?这让我觉得继承 ViewModels 不是一个好主意?

How is this situation usually handled?这种情况通常如何处理? Should I just jam all logic for each page/view into the one MerchandiserViewModel ?我是否应该将每个页面/视图的所有逻辑都塞到一个MerchandiserViewModel中? I want my code to be as clean an separated as possible, so would like to avoid this if possible.我希望我的代码尽可能干净和分离,所以如果可能的话想避免这种情况。

AFTER THOUGHT Am I able to access the properties of the MerchandiserViewModel in static Resource in C#?经过思考,我是否能够访问 C# 中 static 资源中的MerchandiserViewModel的属性? this way I could pass the required properties to the new ViewModel without inheriting the MerchandiserViewModel ... keen to hear thoughts on this?这样我就可以将所需的属性传递给新的 ViewModel 而无需继承MerchandiserViewModel ... 想听听对此的想法吗?

The MerchandiserViewModel has a SelectedMerchandiser property that holds the selected Merchandiser from the ItemSelected in a ListView MerchandiserViewModel 有一个 SelectedMerchandiser 属性,该属性保存从 ListView 中的 ItemSelected 中选择的 Merchandiser

According to your description, you want to binding for ListView, for MerchandiserViewModel, you don't need to inherit other ViewModels, I suggest you can take a look the Model-View-ViewModel Pattern根据你的描述,你要绑定ListView,对于MerchandiserViewModel,不需要继承其他ViewModel,建议你看看Model-View-ViewModel Pattern

I do one sample that binding ListView using MVVM, please take a look.我做了一个使用 MVVM 绑定 ListView 的示例,请看一下。

<StackLayout>
        <ListView
            x:Name="listview1"
            HasUnevenRows="True"
            ItemsSource="{Binding mers}"
            SelectedItem="{Binding selecteditem}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Label
                                FontSize="Large"
                                Text="{Binding Name}"
                                VerticalOptions="Center" />

                            <Label
                                FontSize="Small"
                                Text="{Binding PhoneNumber}"
                                VerticalOptions="Center" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

The model class,contains some properties that binding to UI. model class 包含一些绑定到 UI 的属性。

 public class Merchandiser
{
    public string Name { get; set; }    
    public string PhoneNumber { get; set; }
    
}

The MerchandiserViewmodel class, the view model implements properties and commands to which the view can data bind to, and notifies the view of any state changes through change notification events. MerchandiserViewmodel class,视图 model 实现视图可以数据绑定到的属性和命令,并通过更改通知事件通知视图任何 state 更改。 The properties and commands that the view model provides define the functionality to be offered by the UI, but the view determines how that functionality is to be displayed.视图 model 提供的属性和命令定义了 UI 提供的功能,但视图决定了如何显示该功能。

 public class MerchandiserViewmodel:ViewModelBase
{
    public ObservableCollection<Merchandiser> mers { get; set; }
    private Merchandiser _selecteditem;
    public Merchandiser selecteditem
    {
        get { return _selecteditem; }
        set
        {
            _selecteditem = value;
            RaisePropertyChanged("selecteditem");
        }
    }
    public MerchandiserViewmodel()
    {
        mers = new ObservableCollection<Merchandiser>();
        getdata();
    }
    private void getdata()
    {
        for(int i=0;i<20;i++)
        {
            Merchandiser mer = new Merchandiser();
            mer.Name = "merchandiser "+i;
            mer.PhoneNumber = "123";
            mers.Add(mer);

        }
    }
}

The ViewModelBase is class that implementinf INotifyPropertyChanged interface, notify data changed. ViewModelBase是class,实现了INotifyPropertyChanged接口,通知数据发生变化。 For MerchandiserViewmodel, the Selected Merchandiser(selecteditem) must implement INotifyPropertyChanged to notify data change when you selected item from ListView every time.对于 MerchandiserViewmodel,Selected Merchandiser(selecteditem) 必须实现 INotifyPropertyChanged 以在您每次从 ListView 中选择项目时通知数据更改。

public class ViewModelBase : INotifyPropertyChanged
{
   
    public event PropertyChangedEventHandler PropertyChanged;

   
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Binding ViewModel to ContentPage将 ViewModel 绑定到 ContentPage

 public partial class Page10 : ContentPage
{
    public Page10()
    {
        InitializeComponent();
        this.BindingContext = new MerchandiserViewmodel();
    }
}

Update:更新:

If you want to navigate to detailed page when select ListView item, you can use constructor pass by value in ListView_ItemSelected event.如果您想在 select ListView 项目时导航到详细页面,您可以在 ListView_ItemSelected 事件中使用构造函数传递值。

<StackLayout>
        <ListView
            x:Name="listview1" ItemSelected="listview1_ItemSelected" SelectionMode="Single"
            HasUnevenRows="True"
            ItemsSource="{Binding mers}"
            SelectedItem="{Binding selecteditem}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <Label
                                FontSize="Large"
                                Text="{Binding Name}"
                                VerticalOptions="Center" />

                            <Label
                                FontSize="Small"
                                Text="{Binding PhoneNumber}"
                                VerticalOptions="Center" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

  private async void listview1_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        Merchandiser item = (Merchandiser)e.SelectedItem;
       await Navigation.PushAsync(new simplecontrol.Page29(item));
    }

Detailed Page:详细页面:

<ContentPage.Content>
    <StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Name: " />
            <Label
                FontSize="Large"
                Text="{Binding Name}"
                VerticalOptions="Center" />
        </StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="PhoneNumber: " />
            <Label
                FontSize="Small"
                Text="{Binding PhoneNumber}"
                VerticalOptions="Center" />
        </StackLayout>


    </StackLayout>
</ContentPage.Content>

public partial class Page29 : ContentPage
{
    public Page29(Merchandiser mer)
    {
        InitializeComponent();
        this.BindingContext = mer;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM