[英]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. MerchandiserViewModel
在App.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
,例如MerchandiserProfile
、 EditProfile
等。我创建一个新的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.