Materialdesigninxamltoolkit: Issue with Binding within the Dialogs

Created on 12 Nov 2017  路  7Comments  路  Source: MaterialDesignInXAML/MaterialDesignInXamlToolkit

Hi,
as I am reading the documentation it says that all dialogs will have access to its underlying view (grayed out) DataContext. VS 2017 Designer is confirming that by Intellisense.
I run into issue that maybe Intellisense is working fine, but this Binding is not working in runtime.

I have prepared a quick sample to show you my concerns. The "ImportDDL" button opens a Dialog, which contains two buttons. First button executes ImportDDLCommand and binds the property from underlying DataContext. _In fact the command is never executed and the Content is never bound._

The "Cancel" button just executes the static CloseDialogCommand.

Please take a look:
https://github.com/iXmerof/BindingIssueSample

All 7 comments

I have prepared a quick sample to show you my concerns. The "ImportDDL" button opens a Dialog, which contains two buttons. First button executes ImportDDLCommand and binds the property from underlying DataContext. In fact the command is never executed and the Content is never bound.

The underlying DataContext is null, thats why your bindings are not executed.

Im not sure why that is, but i got it working when using StaticResourceBindings.
See below:

<Window x:Class="XamlToolkitBindingIssue.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:XamlToolkitBindingIssue"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        Title="MainWindow"
        Width="525"
        Height="350">

    <Window.Resources>
        <local:MainWindowsViewModel x:Key="ViewModel" />

        <ControlTemplate x:Key="UserControl">
            <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
                <StackPanel.Resources>
                    <DataTemplate x:Key="InitProgressTemplate">
                        <StackPanel Margin="16">
                            <Button Margin="20px,10px"
                                    Command="{Binding CurrentView.ImportDDLComand, Source={StaticResource ViewModel}}"
                                    Content="{Binding CurrentView.FriendlyName, Source={StaticResource ViewModel}}" />
                            <Button Margin="20px,10px"
                                    Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
                                    Content="Cancel" />
                        </StackPanel>
                    </DataTemplate>

                    <DataTemplate x:Key="StandardProgressTemplate">
                        <StackPanel Margin="16">
                            <ProgressBar Margin="16"
                                         HorizontalAlignment="Center"
                                         IsIndeterminate="True"
                                         Style="{DynamicResource MaterialDesignCircularProgressBar}"
                                         Value="{Binding CurrentView.CurrentProgress, Source={StaticResource ViewModel}}" />
                            <TextBlock VerticalAlignment="Center" Text="Fetching users details" />
                            <TextBlock VerticalAlignment="Center" Text="{Binding CurrentView.CurrentProgress, Source={StaticResource ViewModel}}" />
                        </StackPanel>
                    </DataTemplate>

                    <DataTemplate x:Key="ProgressFinishedTemplate">
                        <StackPanel Margin="16">
                            <TextBlock VerticalAlignment="Center" Text="Done!" />
                            <TextBlock Margin="0,10,0,10" Text="{Binding CurrentView.ProgressResult, Source={StaticResource ViewModel}}" />
                            <Button HorizontalAlignment="Center"
                                    Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
                                    Content="Close" />
                        </StackPanel>
                    </DataTemplate>

                </StackPanel.Resources>

                <Button Margin="20px,10px"
                        Command="{Binding ShowDialogCommand}"
                        Content="Import DDL">
                    <Button.CommandParameter>
                        <ContentControl Width="200px"
                                        Height="160px"
                                        Margin="20px">
                            <ContentControl.Style>
                                <Style TargetType="ContentControl">
                                    <Setter Property="ContentTemplate" Value="{StaticResource InitProgressTemplate}" />
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding CurrentView.CurrentProgress, Source={StaticResource ViewModel}}" Value="1">
                                            <Setter Property="ContentTemplate" Value="{StaticResource StandardProgressTemplate}" />
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding CurrentView.CurrentProgress, Source={StaticResource ViewModel}}" Value="100">
                                            <Setter Property="ContentTemplate" Value="{StaticResource ProgressFinishedTemplate}" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </ContentControl.Style>
                        </ContentControl>
                    </Button.CommandParameter>
                </Button>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>

    <materialDesign:DialogHost DataContext="{Binding CurrentView, Source={StaticResource ViewModel}}" Identifier="RootDialog">
        <StackPanel Margin="5px,10px" Orientation="Vertical">

            <TextBlock Text="Hello" />
            <Rectangle Height="1px"
                       Margin="0,20px"
                       Fill="LightGray" />

            <ContentControl Content="{Binding}" Template="{StaticResource UserControl}" />

        </StackPanel>
    </materialDesign:DialogHost>
</Window>

Thank you, you got me an idea. I cannot move the code exactly as you pointed out, but I think I can hack something out.
Can we consider that this is an issue, or I am using the toolkit in incorrect way?
In free time I'll do some debugging, maybe I could fix it.

I know there is dodgy stuff with the dialoghost, where it does not behave like you'd expect. Maybe someone else can jump in here. It has been a while, since i've dealt with the dialoghost outside my own project.

Yeah this is a common problem. How I have onvercome the problem is to write a class called BindingProxy:

public class BindingProxy : Freezable
    {
        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }

Then in your XAML usercontrol or window resources add:

<UserControl.Resources>
        <domain:BindingProxy x:Key="proxy" Data="{Binding}"/>

<DataTemplate x:Key="myDialog">
<DockPanel LastChildFill="True" Width="450" MaxHeight="400" DataContext="{StaticResource proxy}">
<TextBlock Text="{Binding Data.MyProperty,UpdateSourceTrigger=PropertyChanged}"/>
<Button Command="{Binding MyCommand}"/>

</DockPanel>
</DataTemplate>

</UserControl.Resources>

Key thing is to remember to add "Data." before your binding to the property from your VM.

Then obviously bind your DialogHost DialogContentTemplate bind as appropriate to the correct datatemplate. I got this from somewhere on here or the internet but it does work....very well.

Thank you a lot, that solves the problem. Still sounds like a workaround, but working and elegant workaround. Sorry for late response, I just started working on my project again.

@ixmerof no problems dude, I feel your pain but this was the only thing that worked for me and to be honest have not run into any problems since using this approach.

Was this page helpful?
0 / 5 - 0 ratings