【发布时间】:2019-12-07 16:48:23
【问题描述】:
在接近 Xamarin 形式的跨平台开发时,我在为可重用控件的定义而苦苦挣扎。
作为第一个非常基本的示例,我开发了一个虚拟组件,如下所示:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vmBase="clr-namespace:TestApp.ViewModels.Base"
mc:Ignorable="d"
vmBase:ViewModelLocator.AutoWireViewModel="True"
x:Class="TestApp.Views.Templates.HashtagContainerTemplateView"
x:Name="this">
<ContentView.Content>
<StackLayout BindingContext="{Reference this}">
<Label Text="{Binding Test}"/>
</StackLayout>
</ContentView.Content>
</ContentView>
后面的代码在哪里:
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TestApp.Views.Templates
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HashtagContainerTemplateView : ContentView
{
public static readonly BindableProperty TestProperty = BindableProperty.Create(
propertyName: nameof(Test),
returnType: typeof(string),
declaringType: typeof(HashtagContainerTemplateView),
defaultBindingMode: BindingMode.TwoWay,
defaultValue: "I am the default value",
propertyChanged: TestPropertyChanged);
private static void TestPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
System.Diagnostics.Debugger.Break(); // This is called only when binding with constant values
}
public string Test
{
get => (string)GetValue(TestProperty);
set
{
SetValue(TestProperty, value);
System.Diagnostics.Debugger.Break(); // This is never called
}
}
public HashtagContainerTemplateView()
{
InitializeComponent();
}
}
}
我正在尝试通过将 Test 属性与父 ViewModel 设置的值绑定来将此视图加载到页面中,如下所示:
namespace TestApp.ViewModels
{
public class MainViewModel : BaseViewModel
{
private string _testString;
public string TestString
{
get => _testString;
set
{
_testString = value;
RaisePropertyChanged();
}
}
public MainViewModel()
{
}
// This is called by the View Model Locator
public override async Task InitializeAsync(object navigationData)
{
TestString = "I am the binded string";
await base.InitializeAsync(navigationData);
}
}
}
最后,视图被加载到父页面中:
<templates:HashtagContainerTemplateView Test="I am a costant string"/><!--This Works-->
<templates:HashtagContainerTemplateView Test="{Binding TestString}"/> <!--Not Working-->
运行应用程序时,显示的标签为:I am a costant string 符合预期 I am the default value 是属性的默认值,而不是我通过绑定传递的值
经过一些调试后,我意识到只有在与常量值绑定时才会调用 TestPropertyChanged,并且永远不会调用 Test setter - 请参阅上面代码中的断点 - 所以我认为这就是重点......
我知道有很多这样的话题,即使在 SO 上也是如此,但我真的无法让它发挥作用......我相信我错过了一些非常简单的东西......
最后说明:我使用 Microsoft eShopOnContainers 项目作为参考,因此我使用 View Model Locator 方法。这就是为什么初始化不在 ctor 中而是在 InitializeAsync 函数中的原因。
Microsoft 本身在文档中有关于 Content Views 的部分,但没有使用任何绑定...
【问题讨论】:
-
与内容视图绑定相关的一切看起来都是正确的。您是否尝试将
TestString属性绑定到常规标签,只是为了检查视图模型是否正确连接?也不清楚为什么您的内容视图中需要vmBase:ViewModelLocator.AutoWireViewModel="True"? -
您的问题解决了吗?
-
@ValeriyKovalenko View Model Locator 实际上是问题所在!删除那个顺便说一句没用的,解决了问题。
标签: xaml xamarin mvvm xamarin.forms