I am attempting to make a customised title bar for use in WPF applications, partly in order to learn / practice using usercontrols. I have done what I believe I need to do to bind a command in the usercontrol view model to a property (windowstate) of the mainwindow and the press of a button, but although the command is executing when the button is pressed, the windowstate of the mainwindow containing the usercontrol does not change.
Is there something that I have not understood about the binding here? I feel like I have followed all the instructions I could find online to the letter! (obviously I have not)
Here's the usercontrol xaml:
<UserControl x:Class="UserControls.TitleBar"
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"
xmlns:vm="clr-namespace:ViewModels"
mc:Ignorable="d">
<UserControl.DataContext>
<vm:TitleBar_ViewModel/>
</UserControl.DataContext>
<Button Command="{Binding MaximiseCommand}" />
</UserControl>
and the code in the viewmodel looks like this:
namespace ViewModels
{
public class TitleBar_ViewModel : DependencyObject, INotifyPropertyChanged
{
public TitleBar_ViewModel() { }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private WindowState _windowState;
public WindowState WindowState
{
get
{ return _windowState; }
set
{
_windowState = value;
OnPropertyChanged();
}
}
private ICommand _maximiseCommand;
public ICommand MaximiseCommand
{
get
{
if (_maximiseCommand == null)
{
_maximiseCommand = new RelayCommand(param => this.Maximise(), param => true);
}
return _maximiseCommand;
}
}
private void Maximise()
{
WindowState = WindowState.Maximized;
}
}
}
The xaml for the mainwindow that uses the usercontrol is as follows:
<Window x:Class="Demo.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:uc="clr-namespace:UserControls;assembly=UserControls"
mc:Ignorable="d"
WindowState="{Binding WindowState,ElementName=Titlebar}">
<Grid>
<uc:TitleBar x:Name="Titlebar"/>
</Grid>
</Window>
I've kept things as simple as I possibly can for this demonstration so hopefully you are able to give some pointers as to some essential part of the build process that I have missed, that causes the mainwindow windowstate to be unaffected by the button press.
Any pointers will be great; this use of user controls is really throwing me and I really want to start using it to avoid replicating code over and again for each application!
Your Usercontrol
has no WindowState
property, but the DataContext
of it.
So:
WindowState="{Binding DataContext.WindowState,ElementName=Titlebar}"