问题
I've got a FlipView that shows Figurines. Figurines contain a Path to their image.
Binding this property to a regular DataTemplate is ok. (the code below works fine)
</DataTemplate>
<Canvas x:Name="DefaultImageCanvas" Width="660" Height="372">
<Image Name="imageFlip" Width="660" Height="372" Source="{Binding Path}"
Stretch="Uniform" />
</Canvas>
</DataTemplate>
But when using my UserControl instead, it doesnt work anymore:
<DataTemplate>
<local:FigurineStickerUserControl Width="660" Height="372"
FigurinePath="{Binding Path}"/>
</DataTemplate>
The FigurinePath DP is never set. (If I use a hardcoded string, its fine.) Here is the error in the output:
Error: BindingExpression path error: 'Path' property not found on 'Com.Test.ViewModels.UserControl.FigurineStickerUserControlViewModel, eSmart.ViewModels, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. 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')
It looks like the DataTemplate tries to assign the Figurine as the DataContext of my UserControl, then retrieve the property from my UC's DataContext. But my UC has its own DataContext (its ViewModel) and I don't want to remove it.
Unfortunately with WinRT/UWP there is no FindAncestor tricks that I can do with the Binding. I already tried this: (FlipFigurine being the FlipView object)
<local:FigurineStickerUserControl Width="660" Height="372"
FigurinePath="{Binding SelectedItem.Path, ElementName=FlipFigurine}"/>
It doesnt work. Even changing the DP to object and trying the following doesnt work, the setter of the DP is never called. No error in the log though.
FigurinePath="{Binding SelectedItem, ElementName=FlipFigurine}"
Is there any way to access the actual Figurine object and simply bind its Path property to the FigurinePath property of my UC??
回答1:
As there is no FindAncestor, I think your only hope is to do little refactoring. Here's a sample which hopefully gives you an idea of how to get around the issue:
https://github.com/mikoskinen/uwpusercontrolbinding/tree/master
Here's the main parts from the code:
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()
{
}
}
For some reference related to the example, here's an article from Jerry Nixon.
来源:https://stackoverflow.com/questions/34332815/binding-a-usercontrol-dp-from-datatemplate-uwp