This is a similar problem to WPF Binding : Casting in binding path, where I need to cast an object in a XAML binding statement. But I can't seem to understand how to craft the binding in my particular case.
The answer to that question references PropertyPath XAML Syntax, and the relevant section is (I believe) Single Property, Attached or Otherwise Type-Qualified
.
In my case, in my main View Model I have a dictionary that maps strings to objects that implement a base interface:
Dictionary<string, IFlintStone> FlintStones { get; set;}
public interface IFlintStone { Walk, Talk etc}
public class FlintStone : IFlintStone { .. }
However I also have these additional objects and interfaces which subclass the base object:
public interface IFred : IFlintStone { Eat, Drink, Yell etc }
public interface IWilma : IFlintStone { Wash, Clean, Cook etc }
public class Fred : FlintStone, IFred {..}
public class Wilma : FlintStone, IWilma {..}
And eventually I populate my dictionary like:
FlintStones["Fred"] = new Fred();
FlintStones["Wilma"] = new Wilma();
Now, in my XAML I have a user control for rendering a Fred
object, and another one for rendering a Wilma
object. I can set the data context of these user controls doing something like:
<FredControl DataContext="{Binding Path=FlintStones[Fred]}" />
<WilmaControl DataContext="{Binding Path=FlintStones[Wilma]}" />
However my understanding is that this will only expose the IFlintStone
components of those objects to their respective user controls. But I want to expose IFred
to the <FredControl>
and IWilma
to the <WilmaControl>
Is this possible and what would the binding syntax be in this case?
Using ideas from the links I referenced above, I have tried things like:
<FredControl DataContext="{Binding path=(myns:Fred.FlintStones[Fred])}" />
and
<FredControl DataContext="{Binding path=(myns:Fred).FlintStones[Fred]}" />
(Where myns
is an xaml namespace definition pointing to the Fred
object in the assembly.)
But the program either crashes and burns on start, or it complains that it can't find Fred
as a property of the current data context.
Here is a working version of my interpretation of your issue:
MainWindow.xaml
<Window x:Class="WpfApplication22.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication22"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock Text="{Binding Path=FlintStones[Fred].FlintStone}" />
<TextBlock Text="{Binding Path=FlintStones[Fred].(local:Fred.Yell)}" />
<local:FredControl DataContext="{Binding Path=FlintStones[Fred]}" />
<TextBlock />
<TextBlock Text="{Binding Path=FlintStones[Wilma].FlintStone}" />
<TextBlock Text="{Binding Path=FlintStones[Wilma].(local:Wilma.Clean)}" />
<local:WilmaControl DataContext="{Binding Path=FlintStones[Wilma]}" />
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Collections.Generic;
namespace WpfApplication22
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public Dictionary<string, IFlintStone> FlintStones { get; set; }
public MainWindow()
{
InitializeComponent();
FlintStones = new Dictionary<string, IFlintStone>();
FlintStones["Fred"] = new Fred();
FlintStones["Wilma"] = new Wilma();
this.DataContext = this;
}
}
public interface IFlintStone
{
string FlintStone { get; set; }
}
public interface IFred : IFlintStone
{
string Yell { get; set; }
}
public interface IWilma : IFlintStone
{
string Clean { get; set; }
}
public class Fred : IFred
{
public string FlintStone { get; set; }
public string Yell { get; set; }
public Fred()
{
FlintStone = "Fred Flintstone";
Yell = "Yabba Dabba Doo";
}
}
public class Wilma : IWilma
{
public string FlintStone { get; set; }
public string Clean { get; set; }
public Wilma()
{
FlintStone = "Wilma Flintstone";
Clean = "Mammoth Dish Washer";
}
}
}
FredControl.xaml
<UserControl x:Class="WpfApplication22.FredControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Background="Beige">
<TextBlock Text="{Binding FlintStone}" />
<TextBlock Text="{Binding Yell}" />
</StackPanel>
</UserControl>
WilmaControl.xaml
<UserControl x:Class="WpfApplication22.WilmaControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Background="AntiqueWhite">
<TextBlock Text="{Binding FlintStone}" />
<TextBlock Text="{Binding Clean}" />
</StackPanel>
</UserControl>
FredControl.xaml.cs and WilmaControl.xaml.cs are unmodified (just InitializeComponent(); in the constructors).
And a screenshot:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With