Search code examples
c#wpfmvvmmef

WPF plugin architecture itemscontrol binding not working


We encountered an interesting behavior on .Net 4.5 (4.6.2 also tested). The project has multiple plugin dlls.

main exe will load DataTemplates (view) and ViewModels from DLLs using MEF.

  1. if StepView and StepVm and main frame code are in one project (not using MEF), The 2 buttons I show below are working.
  2. if move StepView and StepVm to plugin dll, only second button will work. First one shows binding error in output console. need to talk to manager if I can post error msg here, just wpf standard binding error.

Can anyone share some insights here? Thanks.

StepView

<UserControl
x:Class="StepView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ScriptHighlighter"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DataContext="{d:DesignInstance local:StepVm}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
    <ItemsControl x:Name="XItemsControl" ItemsSource="{Binding Names}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Button
                        Content="Not Wokring in plugin mode"
                        Command="{Binding ElementName=XItemsControl, Path=DataContext.DeleteCommand}"
                        CommandParameter="{Binding}" />
                    <Button
                        Content="Wokrs in plugin mode"
                        Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}"
                        CommandParameter="{Binding}" />
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

StepVm

public class StepVm:ViewModelBase
{
    public StepVm()
    {
        this.Names = new List<string>(){"1", "2", "3"};
    }
    public List<string> Names { get; set; }
    public ICommand DeleteCommand => new RelayCommand<string>(n =>
    {
        Debug.WriteLine($"logic to delete  {n}");
    });
}

Solution

  • Because MEF loads your UserControl dynamically into the Visual Tree, you are likely to have issues with NameScope, which I think is whats happening here.

    WPF XAML Namescopes

    To be honest, your use of ElementName binding is problematic, because your are in a DateTemplate which is an encapsulation boundary, so although it works outside MEF its not a typically supported scenario.