WindowChrome causing issues with view ContentControl binding?

51 Views Asked by At

I've been working on a small tool for ISO integration and I decided to use WPF for the UI. I'm also doing my best to follow the MVVM pattern for future projects. For the main window, I decided to use WindowChrome so I could keep resizing with a restyled window, however, when I try to select a different view, it causes a exception. I tested it and it does work fine, but as soon as I try to bind the content to the templates content, it seems to cause issues with changing the current view.

Main window xaml:

<WindowChrome.WindowChrome>

    <WindowChrome ResizeBorderThickness="{Binding ResizeBorderThickness}"
                  CaptionHeight="{Binding TitleHeight}" GlassFrameThickness="0"/>

</WindowChrome.WindowChrome>

<Window.Resources>

    <Style TargetType="{x:Type local:OSToolWPF}">

        <Setter Property="Template">

            <Setter.Value>

                <ControlTemplate TargetType="{x:Type Window}">

                    <Border Padding="{Binding OuterMarginThickness}">

                        <Grid>

                            <Border CornerRadius="{Binding WindowCornerRadius}"
                                    Background="{StaticResource BackgroundLightBrush}">

                                <Border.Effect>

                                    <DropShadowEffect ShadowDepth="0" Opacity=".2"/>

                                </Border.Effect>

                            </Border>

                            <Grid>

                                <Grid.RowDefinitions>

                                    <RowDefinition Height="{Binding TitleHeightGridLength, FallbackValue=50}"/>

                                    <RowDefinition Height="*"/>

                                </Grid.RowDefinitions>

                                <Border CornerRadius="10 10 0 0"
                                        Background="{StaticResource BackgroundDarkBrush}">

                                    <Grid>

                                        <Grid.ColumnDefinitions>

                                            <ColumnDefinition Width="*"/>

                                            <ColumnDefinition Width="Auto"/>

                                        </Grid.ColumnDefinitions>

                                        <Viewbox Margin="25 0 0 0" HorizontalAlignment="Left">

                                            <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Title}"/>

                                        </Viewbox>

                                        <StackPanel Grid.Column="1" Orientation="Horizontal">

                                            <Button Style="{StaticResource ButtonBase}" Command="{Binding Minimize}" Width="50">

                                                <Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Minimize.png" Stretch="None"/>

                                            </Button>

                                            <Button Style="{StaticResource ButtonBase}" Command="{Binding Maximize}" Width="50">

                                                <Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Windowed.png" Stretch="None"/>

                                            </Button>

                                            <Button Style="{StaticResource ButtonBase}" Command="{Binding Close}" Width="50">

                                                <Image Style="{StaticResource ControlImage}" Source="/Assets/Top/Close.png" Stretch="None"/>

                                            </Button>

                                        </StackPanel>

                                    </Grid>

                                </Border>

                                <Grid Grid.Row="1">

                                    <Grid.ColumnDefinitions>

                                        <ColumnDefinition Width="*"/>

                                        <ColumnDefinition Width="5*"/>

                                    </Grid.ColumnDefinitions>

                                    <Grid>

                                        <Grid.RowDefinitions>

                                            <RowDefinition Height="Auto"/>

                                            <RowDefinition Height="*"/>

                                            <RowDefinition Height="Auto"/>

                                        </Grid.RowDefinitions>

                                        <StackPanel>

                                            <Button Style="{StaticResource ButtonBase}" Tag="Registry" Command="{Binding Menu}"
                                                    Content="Registry" FontSize="20" Height="50" CommandParameter="{Binding 
                                                    RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>

                                            <Button Style="{StaticResource ButtonBase}" Tag="Services" Command="{Binding Menu}"
                                                    Content="Services" FontSize="20" Height="50" CommandParameter="{Binding 
                                                    RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>

                                            <Button Style="{StaticResource ButtonBase}" Tag="Visuals" Command="{Binding Menu}"
                                                    Content="Visuals" FontSize="20" Height="50" CommandParameter="{Binding 
                                                    RelativeSource={RelativeSource Mode=Self}, Path=Tag}"/>

                                        </StackPanel>

                                        <Button Grid.Row="2" Style="{StaticResource ButtonBase}"
                                                Content="Exit" FontSize="20" Command="{Binding Close}"
                                                Height="50"/>

                                    </Grid>

                                    <Border Grid.Column="1">

                                        <ContentControl Content="{TemplateBinding Content}"/>

                                    <Border/>

                                </Grid>

                            </Grid>

                        </Grid>

                    </Border>

                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

</Window.Resources>

<ContentControl Content="{Binding CurrentView}"/>

Main window view model (the data binding is done in xaml.cs since it needs a window):

public class OSToolViewModel : BaseViewModel
{
    #region Private

    private Window wWindow;
    private object wCurrentView;

    private int wOuterMarginSize = 10;
    private int wWindowRadius = 15;

    #endregion

    public OSToolViewModel(Window window)
    {
        wWindow = window;

        wWindow.StateChanged += (sender, e) =>
        {
            OnPropertyChanged(nameof(ResizeBorderThickness));
            OnPropertyChanged(nameof(OuterMarginSize));
            OnPropertyChanged(nameof(OuterMarginThickness));
            OnPropertyChanged(nameof(WindowRadius));
            OnPropertyChanged(nameof(WindowCornerRadius));
        };

        Menu = new BaseCommand(e => CurrentView = new ExpanderItemsList());
        Minimize = new BaseCommand(e => wWindow.WindowState = WindowState.Minimized);
        Maximize = new BaseCommand(e => wWindow.WindowState ^= WindowState.Maximized);
        Close = new BaseCommand(e => CloseMessage());
    }

    #region Voids

    private void CloseMessage()
    {
        if (DialogBox.Show("Would you like to exit?", "", wWindow.Title, DialogBoxButtons.YesNo) == DialogResult.Yes)
        {
            wWindow.Close();
        }
    }

    #endregion

    #region Commands

    public BaseCommand Menu { get; set; }

    public BaseCommand Minimize { get; set; }

    public BaseCommand Maximize { get; set; }

    public BaseCommand Close { get; set; }

    #endregion

    #region Public

    public object CurrentView
    {
        get { return wCurrentView; }
        
        set
        {
            if (value == wCurrentView)
                return;

            wCurrentView = value;
            OnPropertyChanged(nameof(CurrentView));
        }
    }

    public int ResizeBorder { get; set; } = 6;

    public int OuterMarginSize
    {
        get
        {
            return wWindow.WindowState == WindowState.Maximized ? 0 : wOuterMarginSize;
        }
        set
        {
            wOuterMarginSize = value;
        }
    }

    public int WindowRadius
    {
        get
        {
            return wWindow.WindowState == WindowState.Maximized ? 0 : wWindowRadius;
        }
        set
        {
            wWindowRadius = value;
        }
    }

    public double TitleHeight { get; set; } = 50;

    public Thickness ResizeBorderThickness { get { return new Thickness(ResizeBorder + OuterMarginSize); } }

    public Thickness OuterMarginThickness { get { return new Thickness(OuterMarginSize); } }

    public CornerRadius WindowCornerRadius { get { return new CornerRadius(WindowRadius); } }
    
    public GridLength TitleHeightGridLength { get { return new GridLength(TitleHeight + ResizeBorder); } }

    #endregion
}

The view I'm trying to bind to is a page, so I'm not sure if that would cause issues or not, but I've tried a lot of different combos and the combo I shared causes a exception. If I didn't bind to to the templated content, it would work fine. I'm baffled as to why this happens, and as a side note, the buttons in the window aren't cornered like they should be, so if you have a solution for this too, that would be much appreciated! Thank you and I hope you enjoy your day!

1

There are 1 best solutions below

0
AudioBubble On BEST ANSWER

I just realized this issue was because of the fact I was using a Page rather than a UserControl. Switching the view to a UserControl solved the issue. Hopefully this helps if anyone else runs into this issue.