问题描述
就像Xamarin.Forms.Xaml.BindingExtension
尽其所能来获得有效的绑定上下文以返回与相关源/路径/模式相对应的BindingBase
对象一样,我想创建一个扩展来执行它的伏都教徒也基于有效的绑定上下文。通过IProvideValueTarget
,我设法获得了BindingContext
,但是没有获得有效的绑定上下文,因此,在DataTemplate
中使用时,它总是带给我父辈的有效绑定上下文,而不是比DataTemplate
。我正在尝试在数据模板中找到有效的绑定上下文。
为了更清楚地说明这一点,我在一个简单的PoC中重新创建了问题。
我们有以下模型:
namespace App1.Models
{
public class MyBeautifulModel
{
public string SomeData { get; set; }
public override string ToString()
{
return SomeData;
}
}
}
以下视图模型:
using App1.Models;
using System.Collections.Generic;
namespace App1.viewmodels
{
public class MainPageviewmodel : viewmodelBase
{
public MainPageviewmodel()
{
MyBeautifulModels = new[]
{
new MyBeautifulModel() { SomeData = "DataTemplate Data0" },new MyBeautifulModel() { SomeData = "DataTemplate Data1" },new MyBeautifulModel() { SomeData = "DataTemplate Data2" },};
MyProperty = "Outer Template Data";
}
public IEnumerable<MyBeautifulModel> MyBeautifulModels { get; }
public string MyProperty { get; }
public override string ToString()
{
return MyProperty;
}
}
}
以下标记扩展名:
using System;
using System.Linq;
using System.Reflection;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.Forms.Xaml.Internals;
namespace App1.MarkupExtensions
{
public class PrintContextExtension : IMarkupExtension
{
public object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider.GetService<IProvideValueTarget>() is SimpleValueTargetProvider provider)
{
object[] objectAndParents = (object[])typeof(SimpleValueTargetProvider).GetField("objectAndParents",BindingFlags.Instance | BindingFlags.NonPublic).GetValue(provider);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Object and all its parents:");
foreach (object obj in objectAndParents)
sb.AppendLine(obj.ToString());
sb.AppendLine("First object with binding context:");
BindableObject bindable = (BindableObject)objectAndParents.First(b => b is BindableObject bindableObject && bindableObject.BindingContext != null);
sb.AppendLine(bindable.ToString());
sb.AppendLine("The binding context of that object:");
sb.AppendLine(bindable.BindingContext.ToString());
string result = sb.ToString();
Console.WriteLine(result);
return bindable.BindingContext.ToString();
}
throw new Exception();
}
}
}
以及以下视图:
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:App1.viewmodels"
xmlns:ext="clr-namespace:App1.MarkupExtensions"
mc:Ignorable="d"
x:Class="App1.Views.MainPage"
Padding="20">
<ContentPage.BindingContext>
<vm:MainPageviewmodel/>
</ContentPage.BindingContext>
<ContentPage.Resources>
<Style targettype="Label">
<Setter Property="FontSize" Value="Title"/>
<Setter Property="BackgroundColor" Value="LightGreen"/>
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Built-in Binding: "/>
<Span Text="{Binding MyProperty}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="My Binding: "/>
<Span Text="{ext:PrintContext MyProperty}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Frame BorderColor="DimGray"
CornerRadius="15">
<ListView ItemsSource="{Binding MyBeautifulModels}"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="0,20">
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Built-in Binding: "/>
<Span Text="{Binding SomeData}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<Label BackgroundColor="PaleVioletRed">
<Label.FormattedText>
<FormattedString>
<Span Text="My Binding: "/>
<Span Text="{ext:PrintContext SomeData}"/>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
</StackLayout>
</ContentPage.Content>
</ContentPage>
运行此命令将产生以下控制台输出:
Object and all its parents:
Xamarin.Forms.Span
My Binding:
Xamarin.Forms.Label
Xamarin.Forms.StackLayout
Xamarin.Forms.ViewCell
Xamarin.Forms.DataTemplate
Xamarin.Forms.ListView
Xamarin.Forms.Frame
Xamarin.Forms.StackLayout
App1.Views.MainPage
First object with binding context:
Xamarin.Forms.ListView
The binding context of that object:
Outer Template Data
很抱歉,这个问题看起来太长了,但我希望我的重现步骤能使问题更易于简化和说明。
p看着BindingExtension
's implementation on GitHub,看来IServiceProvider
甚至没有被使用。这对我来说似乎很奇怪-因为它怎么知道它的上下文!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)