如何将视图模型绑定到Xamarin中XAML中的视图?
我有一个非常基本的观点如何将视图模型绑定到Xamarin中XAML中的视图?,xamarin,mvvm,binding,Xamarin,Mvvm,Binding,我有一个非常基本的观点 <ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage" Title="{Binding Title}" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns="http://xamarin.com/schema
<ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage"
Title="{Binding Title}"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns="http://xamarin.com/schemas/2014/forms">
<StackLayout>
<ListView ItemsSource="{Binding Items}"/>
</StackLayout>
<ContentPage/>
来自WPF和UWP中的纯MVVM环境,我希望将视图绑定到XAML中的viewmodel,而不是使用代码隐藏中的this.Binding=viewmodel。我试过:
<ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage"
xmlns:controls="clr-namespace:ThetaRex.InvestmentManager.Merlin.Controls"
BindingContext="{Binding ViewModel}"
Title="{Binding Title}"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns="http://xamarin.com/schemas/2014/forms">
但它不起作用。如何从XAML绑定到ViewModel
注意:我知道我可以在XAML中从头开始创建视图模型,但它不使用视图中代码隐藏所使用的实例,因此这不是一个选项。如果我了解您需要什么,解决方案是构建一个ViewModelLocator,如下所示:
公共静态类ViewModelLocalizator
{
公共静态只读BindableProperty AutoWireViewModelProperty=
CreateAttached(“AutoWireViewModel”,typeof(bool),typeof(ViewModelLocalizator),default(bool),propertyChanged:OnAutoWireViewModelChanged);
公共静态bool GetAutoWireViewModel(BindableObject bindable)
{
return(bool)bindable.GetValue(AutoWireViewModelProperty);
}
公共静态void SetAutoWireViewModel(BindableObject bindable,bool值)
{
bindable.SetValue(AutoWireViewModelProperty,值);
}
///
///验证视图名称并将其与同名视图模型关联。将“视图”后缀替换为“视图模型”
///
AutoWireViewModelChanged上的私有静态无效(BindableObject bindable、object oldValue、object newValue)
{
如果(!(可绑定为元素视图))
{
返回;
}
var viewType=view.GetType();
var viewModelName=viewType.FullName.Replace(“.Views.”,“.ViewModels.”)。Replace(“Page”,“ViewModel”);
var viewModelType=Type.GetType(viewModelName);
如果(viewModelType==null){return;}
var vmInstance=Activator.CreateInstance(viewModelType);
if(vmInstance!=null)
{
view.BindingContext=vmInstance;
}
}
}
可能与@sermet重复-它不是重复的。见附注。该解决方案创建了视图无法访问的全新ViewModel。视图要求它必须能够调用其视图模型上的方法。例如,在上面的示例中初始化时执行LoadItemsCommand.var vm=BindingContext作为ScenarioSelectionViewModel;vm.LoadItemsCommand.Execute(null);
<ContentPage x:Class="ThetaRex.InvestmentManager.Merlin.Views.ScenarioSelectionPage"
xmlns:controls="clr-namespace:ThetaRex.InvestmentManager.Merlin.Controls"
BindingContext="{Binding ViewModel}"
Title="{Binding Title}"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns="http://xamarin.com/schemas/2014/forms">
public static class ViewModelLocalizator
{
public static readonly BindableProperty AutoWireViewModelProperty =
BindableProperty.CreateAttached("AutoWireViewModel", typeof(bool), typeof(ViewModelLocalizator), default(bool), propertyChanged: OnAutoWireViewModelChanged);
public static bool GetAutoWireViewModel(BindableObject bindable)
{
return (bool)bindable.GetValue(AutoWireViewModelProperty);
}
public static void SetAutoWireViewModel(BindableObject bindable, bool value)
{
bindable.SetValue(AutoWireViewModelProperty, value);
}
/// <summary>
/// VERIFY THE VIEW NAME AND ASSOCIATE IT WITH THE VIEW MODEL OF THE SAME NAME. REPLACING THE 'View' suffix WITH THE 'ViewModel'
/// </summary>
private static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
{
if (!(bindable is Element view))
{
return;
}
var viewType = view.GetType();
var viewModelName = viewType.FullName.Replace(".Views.", ".ViewModels.").Replace("Page", "ViewModel");
var viewModelType = Type.GetType(viewModelName);
if (viewModelType == null) { return; }
var vmInstance = Activator.CreateInstance(viewModelType);
if (vmInstance != null)
{
view.BindingContext = vmInstance;
}
}
}
<ContentPage x:Class="YourProject.Views.YourTestPage"
Title="{Binding Title}"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:viewModelBase="clr-namespace:YourProject.ViewModels;assembly=YouProject"
viewModelBase:ViewModelLocalizator.AutoWireViewModel="true"
>
<StackLayout>
<ListView ItemsSource="{Binding Items}"/>
</StackLayout>
<ContentPage/>