MikeR
MikeR

Reputation: 3075

WPF-MVVM-Bind window title to property

My client application can connect to different server applications, therefore I would like to add the connection information to the window title dynamically. The title is bound to a property of the ViewModel and its get is called after starting the app, but than it doesn't get updated anymore, while other controls in the window are still working properly.

Here is the XAML:

<Window x:Class="MyApp.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"
    mc:Ignorable="d"
    xmlns:localVM="clr-namespace:MyApp.ViewModels"
    xmlns:local="clr-namespace:MyApp"
    WindowStartupLocation="CenterScreen"
    Title="{Binding Path=AppTitle}"
    Height="459"
    Width="810">
<Window.Resources>
    [...]
    <localVM:MainWindowViewModel x:Key="Windows1ViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource Windows1ViewModel}">
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Canvas Grid.Row="0">
        <Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=Menu}"/>
        <Label Content="{Binding Path=ConnectionProperty}" Canvas.Right="0" Canvas.Bottom="0"/>
    </Canvas>
 </Grid>
</Window>

The Title is bound to AppTitle, while Label is bound to ConnectionProperty, which is working fine. In the XAML.cs I set the ViewModel to the DataContext of the View:

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainWindowViewModel();
}

The constructor of the MainWindowViewModel:

public MainWindowViewModel()
{
    MenuItemViewModel server = new MenuItemViewModel { Text = ServerMenu };
    Menu.Add(server);
    AppTitle = "My application title";
    SetConnectionMenuEntry(false);
    //[.. dynamically build my menu ..]
}

After starting the application, the Title is shown correctly. Then I connect to a server:

private void ConnectToServer()
{
    //[.. connect to server ..]
    if (connected)
    {
        SetConnectionMenuEntry(true);
        ConnectionProperty = " - connected to " + serverProxy.url;
        AppTitle  = appTitle + connectionProperty;
    }
}

After this, the Title remains the same, while the Label gets the ConnectionProperty value.

Here is the definition of both properties, which is nearly identical:

    private string appTitle;
    public string AppTitle 
    {
        get { return appTitle; }
        set 
        {
            if (this.appTitle != value)
            {
                this.appTitle = value;
                RaisePropertyChanged(() => AppTitle);
            }
        }
    }

    private string connectionProperty = "";
    public string ConnectionProperty
    {
        get { return this.connectionProperty; }
        set
        {
            if (this.connectionProperty != value)
            {
                this.connectionProperty = value;
                RaisePropertyChanged(() => ConnectionProperty);
            }
        }
    }

Any idea why the Title is not updated, but the Label?

Upvotes: 2

Views: 9488

Answers (2)

Hugo Dozois
Hugo Dozois

Reputation: 8420

As stated by the original poster of the question:


I commented out the lines I needed to remove to make it work properly :

<Window x:Class="MyApp.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"
    mc:Ignorable="d"
    xmlns:localVM="clr-namespace:MyApp.ViewModels"
    xmlns:local="clr-namespace:MyApp"
    WindowStartupLocation="CenterScreen"
    Title="{Binding Path=AppTitle}"
    Height="459"
    Width="810">
<Window.Resources>
    [...]
    <!-- <localVM:MainWindowViewModel x:Key="Windows1ViewModel" /> [Edit: 2 times set] -->
</Window.Resources>
<Grid> <!-- Edit removed: DataContext="{StaticResource Windows1ViewModel}" -->
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Canvas Grid.Row="0">
        <Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=Menu}"/>
        <Label Content="{Binding Path=ConnectionProperty}" Canvas.Right="0" Canvas.Bottom="0"/>
    </Canvas>
 </Grid>
</Window>

Upvotes: 0

Myrtle
Myrtle

Reputation: 5851

You have the Windows1ViewModel in the Grid.Resources, however you create a new DataContext for the window from code. You have two instances of the ViewModel this way.

Upvotes: 1

Related Questions