簡體   English   中英

ViewModels是否應該繼承Xamarin.Forms中的其他ViewModels?

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

ViewModels應該繼承其他ViewModels嗎?

我有一個MerchandiserViewModel ,其中包含Merchandiser model 的基本屬性和數據庫函數。

MerchandiserViewModel有一個SelectedMerchandiser屬性,該屬性保存從ListView中的ItemSelected中選擇的Merchandiser

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...

}

MerchandiserViewModelApp.xaml中實例化為Static Resource ,因此我只有一個視圖實例 model。

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>

對於與 Merchandiser 相關的每個View ,例如MerchandiserProfileEditProfile等。我創建一個新的ViewModel並繼承MerchandiserViewModel

MerchandiserProfileViewModel.cs繼承 MerchandiserViewModel

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

問題是......當我創建一個新的[Page]ViewModel並繼承“MerchandiserViewModel”時,我收到以下錯誤消息。

錯誤信息

我認為這可能是因為創建了MerchandiserViewModel的新實例,所以我沒有引用初始SelectedMerchandiser屬性。

這讓我覺得繼承 ViewModels 不是一個好主意?

這種情況通常如何處理? 我是否應該將每個頁面/視圖的所有邏輯都塞到一個MerchandiserViewModel中? 我希望我的代碼盡可能干凈和分離,所以如果可能的話想避免這種情況。

經過思考,我是否能夠訪問 C# 中 static 資源中的MerchandiserViewModel的屬性? 這樣我就可以將所需的屬性傳遞給新的 ViewModel 而無需繼承MerchandiserViewModel ... 想聽聽對此的想法嗎?

MerchandiserViewModel 有一個 SelectedMerchandiser 屬性,該屬性保存從 ListView 中的 ItemSelected 中選擇的 Merchandiser

根據你的描述,你要綁定ListView,對於MerchandiserViewModel,不需要繼承其他ViewModel,建議你看看Model-View-ViewModel Pattern

我做了一個使用 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>

model class 包含一些綁定到 UI 的屬性。

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

MerchandiserViewmodel class,視圖 model 實現視圖可以數據綁定到的屬性和命令,並通過更改通知事件通知視圖任何 state 更改。 視圖 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);

        }
    }
}

ViewModelBase是class,實現了INotifyPropertyChanged接口,通知數據發生變化。 對於 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));
        }
    }
}

將 ViewModel 綁定到 ContentPage

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

更新:

如果您想在 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));
    }

詳細頁面:

<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