从DataTemplate绑定UserControl DP(UWP)

4
我有一个FlipView,用于展示人物雕塑。雕塑包含了他们图片的路径。
将这个属性绑定到普通的DataTemplate没有问题。(下面的代码可以正常工作)
</DataTemplate>
    <Canvas x:Name="DefaultImageCanvas" Width="660" Height="372">
        <Image Name="imageFlip" Width="660" Height="372" Source="{Binding Path}"
            Stretch="Uniform" />
    </Canvas>
</DataTemplate>

但是当我使用我的用户控件时,它就不再起作用了:
<DataTemplate>
    <local:FigurineStickerUserControl Width="660" Height="372"
                                      FigurinePath="{Binding Path}"/>
</DataTemplate>

FigurinePath DP 未设置。(使用硬编码的字符串没有问题。)下面是输出中的错误信息:
绑定表达式路径错误:“在'Com.Test.ViewModels.UserControl.FigurineStickerUserControlViewModel, Test.ViewModels, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'上未找到'Path'属性。BindingExpression: Path='Path' DataItem='Com.Test.ViewModels.UserControl.FigurineStickerUserControlViewModel, Test.ViewModels, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; target element is 'Com.Test.Views.FigurineStickerUserControl' (Name='pageRoot'); target property is 'FigurinePath' (type 'Object')”。
看起来DataTemplate试图将Figurine分配为UserControl的DataContext,然后从我的UC的DataContext检索该属性。但是我的UC有自己的DataContext(即其ViewModel),我不想删除它。
不幸的是,在WinRT / UWP中,无法使用Binding进行FindAncestor技巧。我已经尝试过以下方法:(FlipFigurine为FlipView对象)
<local:FigurineStickerUserControl Width="660" Height="372"
                                  FigurinePath="{Binding SelectedItem.Path, ElementName=FlipFigurine}"/>

它不起作用。即使将DP更改为对象并尝试以下操作也无效,DP的setter从未被调用。日志中没有错误。

FigurinePath="{Binding SelectedItem, ElementName=FlipFigurine}"

有没有办法访问实际的Figurine对象并将其Path属性绑定到我的UC的FigurinePath属性?
1个回答

3

由于没有FindAncestor,我认为你唯一的希望是进行一些重构。以下是一个示例,希望能让你了解如何解决这个问题:

https://github.com/mikoskinen/uwpusercontrolbinding/tree/master

这是代码中的主要部分:

MainPage.xaml

<DataTemplate>
    <local:MyUserControl Width="660" Height="372" FigurinePath="{Binding Path}"/>
</DataTemplate>

MainPage.xaml.cs

private ObservableCollection<MyUserControlVm> coll;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    coll = new ObservableCollection<MyUserControlVm>();
    coll.Add(new MyUserControlVm("http://libcloud.readthedocs.org/en/latest/_images/azure.jpg"));
    coll.Add(new MyUserControlVm("http://www.nimbo.com/wp-content/uploads/windows-azure-logo-nimbo1.png"));

    this.Flip.ItemsSource = coll;

    base.OnNavigatedTo(e);
}

MyUserControl.xaml

<Grid>
    <Canvas Width="660" Height="372">
        <Image Width="660" Height="372" Source="{Binding FigurinePath}" Stretch="Uniform" />
    </Canvas>
</Grid>

MyUserControl.xaml.cs

public sealed partial class MyUserControl : UserControl
{
    public static readonly DependencyProperty FigurinePathProperty = DependencyProperty.Register(
        "FigurinePath", typeof (Uri), typeof (MyUserControl), new PropertyMetadata(default(Uri)));

    public Uri FigurinePath
    {
        get { return (Uri) GetValue(FigurinePathProperty); }
        set { SetValue(FigurinePathProperty, value); }
    }

    public MyUserControl()
    {
        this.InitializeComponent();
        (this.Content as FrameworkElement).DataContext = this;
    }
}

MyUserControlVM.cs

public class MyUserControlVm
{
    public Uri Path { get; set; }

    public MyUserControlVm(string url)
    {
        Path = new Uri(url);
    }

    public void VmAction()
    {

    }
}

关于这个例子的一些参考资料,这里有来自Jerry Nixon的文章。


谢谢你,Mikael!我还没有时间测试它,但看起来这似乎是唯一的方法,尽管我希望有一种更优雅的方式(通过xaml)。只是一个细节:我没有将任何内容绑定到CB上,因为我们直接将路径传递给VM,所以DP现在是无用的,不是吗? - jujujuijk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接