Tim
Tim

Reputation: 1661

WPF Bind Window Title to ViewModel Property

I am trying to bind a Window Title to the ViewModel which has a Title property. Below is the MainWindow XAML:

<Window x:Class="MyProject.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
        Title="{Binding Path=Title}" Height="350" Width="525" DataContext="{Binding Source={StaticResource mainWindowViewModel}}">
    <Window.Resources>
        <vm:MainWindow x:Key="mainWindowViewModel"/>
    </Window.Resources>

...

</Window>

When I try to run this, I get the following exception "Provide value on 'System.Windows.StaticResourceExtension' threw an exception. The line number and position point to the DataContext property, and the inner exception states "Cannot find resource named mainWindowViewModel.

Below is the code for the View Model:

namespace MyProject.ViewModel
{
    public class MainWindow : INotifyPropertyChanged
    {
        #region Fields

        private const string TitlebarPrefixString = "My Project";
        private string title = TitlebarPrefixString;

        public string Title {
            get
            {
                return this.title;
            } // End getter
            set
            {    
                this.title = value;
                OnPropertyChanged("Title");
            } // End setter
        } // End property

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            } // End if
        } // End method


        public event PropertyChangedEventHandler PropertyChanged;

    } // End class
} // End namespace

My theory is that the resources are loaded after the attempt to bind the title to the property. When the exception is thrown, the Resources property for the Window is empty.

Is the only solution to set the DataContext in the Code Behind? I can get this to work, but I would prefer to keep it in XAML.

Upvotes: 9

Views: 19963

Answers (2)

Eibi
Eibi

Reputation: 400

A little late but a simple and perfect solution that I am using just in case people are still searching for possibilities:

<Window x:Class="Project.MainWindow"
        Title="{Binding DataContext.ApplicationTitle, ElementName=TheMainView}">

        <views:MainView x:Name="TheMainView"/>

</Window>

Than simply enough, just add a Property to your MainViewModel that is the DataContext of the MainView like so:

public string ApplicationTitle
        {
            get
            {
                var text = "Application Name";
                if (!string.IsNullOrEmpty(_currentFileLoaded))
                {
                    text += $" ({_currentFileLoaded})";
                }

                return text;
            }
        }

Hope it helps..

Upvotes: 0

Jurica Smircic
Jurica Smircic

Reputation: 6455

You can try to set the DataContext using property element syntax:

<Window x:Class="MyProject.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
    Title="{Binding Path=Title}" Height="350" Width="525">
<Window.Resources>
    <vm:MainWindow x:Key="mainWindowViewModel"/>
</Window.Resources>
<Window.DataContext>
  <StaticResourceExtension ResourceKey="mainWindowViewModel"/>
</Window.DataContext>

That should work as the xaml parser will execute StaticResourceExtension after the resources dictionary is set.

But i think maybe even better would be to set the DataContext directly, without declaring it as resource:

<Window x:Class="MyProject.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
    Title="{Binding Path=Title}" Height="350" Width="525">
<Window.DataContext>
    <vm:MainWindow x:Key="mainWindowViewModel"/>
</Window.DataContext>

Upvotes: 13

Related Questions