自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding
Posted
技术标签:
【中文标题】自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding【英文标题】:Xamarin databinding value for custom control evaluates as Xamarin.Forms.Binding 【发布时间】:2016-01-20 03:18:09 【问题描述】:我遇到了 Xamarin.Forms 的问题,使用它的人都知道它与 WPF 非常相似。不幸的是,我遇到了 WPF 从未遇到过的问题。
场景如下:
我的视图模型:
public class ShellViewModel : ViewModelBase
public ShellViewModel()
ActiveViewModel = new ProjectActionOverviewViewModel();
private ShellViewChildModel _activeViewModel;
public ShellViewChildModel ActiveViewModel
get return _activeViewModel;
set
Debug.WriteLine("Updating ActiveViewModel.");
SetValue(ref _activeViewModel, value);
Task.Run(() => value.ActivateAsync());
Debug.WriteLine("Updated ActiveViewModel.");
Xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:MyNamespace.XamarinForms.ViewModels;assembly=MyNamespace.XamarinForms"
xmlns:views="clr-namespace:MyNamespace.XamarinForms.Views;assembly=MyNamespace.XamarinForms"
xmlns:resources="clr-namespace:MyNamespace.XamarinForms.Resources;assembly=MyNamespace.XamarinForms"
xmlns:custom="clr-namespace:MyNamespace.XamarinForms.Views.Custom;assembly=MyNamespace.XamarinForms"
x:Class="MyNamespace.XamarinForms.Views.Pages.ShellView">
<ContentPage.BindingContext>
<viewModels:ShellViewModel></viewModels:ShellViewModel>
</ContentPage.BindingContext>
<Grid BackgroundColor="x:Static resources:Colors.DefaultBackground">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" BackgroundColor="x:Static resources:Colors.CiRed" Padding="14" IsVisible="Binding ActiveViewModel.IsHeaderVisible">
<Label TextColor="x:Static resources:Colors.BrightForeground" FontSize="20" Text="Binding ActiveViewModel.HeaderText"/>
</Grid>
<Grid Grid.Row="1" BackgroundColor="x:Static resources:Colors.DefaultBackground">
<custom:ShellChildPresenter ViewModel="Binding Path=ActiveViewModel"></custom:ShellChildPresenter>
</Grid>
<Grid IsVisible="Binding ActiveViewModel.IsBusy" Grid.Row="0" Grid.RowSpan="2" BackgroundColor="x:Static resources:Colors.DarkBackground" Opacity="0.5">
<ActivityIndicator IsRunning="Binding ActiveViewModel.IsBusy" VerticalOptions="Center" HorizontalOptions="Center"></ActivityIndicator>
</Grid>
</Grid>
</ContentPage>
我的自定义控件:
public class ShellChildPresenter : ContentView
public ShellChildPresenter()
private static readonly BindableProperty ViewModelProperty = BindableProperty.Create<ShellChildPresenter, ShellViewChildModel>(
presenter => presenter.ViewModel,
defaultValue: null,
defaultBindingMode: BindingMode.OneWay,
propertyChanged: ViewModelPropertyChanged);
private static void ViewModelPropertyChanged(BindableObject bindable, ShellViewChildModel oldValue, ShellViewChildModel newValue)
if (newValue != null)
var current = bindable as ShellChildPresenter;
if (current == null)
return;
var view = newValue.CreateContentView();
view.BindingContext = newValue;
current.Content = view;
public ShellViewChildModel ViewModel
get return (ShellViewChildModel)GetValue(ViewModelProperty);
set SetValue(ViewModelProperty, value);
起初,它不断抛出异常,宣布“ViewModel”属性的类型不匹配。为了尝试解决此问题,我将属性类型更改为“对象”,此时 ShellViewModel.ViewModel 中的设置器收到 Xamarin.Forms.Binding 的实例。
谁能发现我做错了什么,这就解释了为什么我得到一个 Binding 实例而不是 ShellViewChildModel?奇怪的是,对于我的 xaml 中的其他控件,我的内容显示得很好。
欢迎任何想法。到目前为止,我的想法已经用尽,文档没有指出我的代码有任何明显的缺陷:/
【问题讨论】:
在获取你的ActiveViewModel
时试试这个; return (ShellViewChildModel)GetValue(ViewModelProperty);
并且在集合中也只需使用您的 ViewModelProperty
,不需要私有支持字段。
@GeraldVersluis 不幸的是,这会导致同样的错误。此外,由于习惯了 WPF,我开始尽可能避免使用 DependencyObject,在这种情况下,我猜想避免使用 BindableObject 也是有意义的。无论如何 - 更改为 BindableObject + 按照建议实施并没有解决这个问题
【参考方案1】:
我讨厌魔法。似乎“更容易”的编程变得更“神奇”的事情发生。更多次然后不是它最终把我搞砸了。对不起,答案之前在这里做简短的评论。
改变
private static readonly BindableProperty ViewModelProperty
到
public static readonly BindableProperty ViewModelProperty
为什么?
赋值
ShellChildPresenter ViewModel="Binding Path=ActiveViewModel"
由 Xaml 解析器解释。首先,它创建一个由“Binding Path=ActiveViewModel”描述的绑定元素。其次,它将“属性”一词附加到末尾,并在 Binding Context 中扫描对象,寻找.....属性以神奇地将其全部连接到。
由于您的........属性是私有的,解析器看不到它。所以它继续前进并按照您告诉它的方式执行 ViewModel=Binding 而不是您想要的 ViewModelProperty=Binding。
就像我说的我讨厌魔法。
【讨论】:
老实说,我同意你的咆哮...如果有警告就可以了。但是它绑定到 clr 属性,而当无法发现“依赖属性”时默默地失败只是......该死的。为什么?!我一直在寻找像18h这样的解决方案...... grrrrrr。然后再次对这样的错误感到不安有助于记住它。谢谢!以上是关于自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding的主要内容,如果未能解决你的问题,请参考以下文章
在父项中设置绑定时,Xamarin.Forms 绑定到自定义控件不起作用