Home > Software design >  Create dependency property for WPF Window itself in its code behind xaml.cs
Create dependency property for WPF Window itself in its code behind xaml.cs

Time:02-05

I have a WPF window which I have changed its borders, title bar and buttons for a custom one. Separately in a ResourceDictionary I have defined the Style that I want to apply to my WPF window. Then I bind that style to my WPF Window using below line of code:

Style="{DynamicResource CustomWindowStyle}" 

Please see all my code posted in another thread that I created to ask for other things. Refer to this thread to see the code (I want to avoid repeating here again).

Now what I am trying to do is to create some custom properties (MyCustomProperty01, MyCustomProperty02) to that WPF Window, some like below:

myDialogView.xaml:

<Window x:Class="myApp.Views.myDialogView"
        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:v="clr-namespace:myApp.Views"
        xmlns:vm="clr-namespace:myApp.ViewModels"
        mc:Ignorable="d" 
        d:DesignHeight="450" d:DesignWidth="800"
        ResizeMode="NoResize"
        SizeToContent="WidthAndHeight"
        Style="{StaticResource CustomWindowStyle}" 
        WindowStyle="None"

        MyCustomProperty01 = "true"
        MyCustomProperty02 = "true">

...and then in the code-behind of this WPF window (xaml.cs) I want to define those dependency properties MyCustomProperty01 and MyCustomProperty02, the ones you see above in the code snippet for the Window.

So I create those dependency properties in the code-behind as below.

myDialogView.xaml.cs (code-behind):

namespace myApp.Views
{
    public partial class myDialogView: Window
    {
        public myDialogView()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty MyCustomProperty01Property =
            DependencyProperty.Register("MyCustomProperty01",
                                        typeof(bool),
                                        typeof(myDialogView),
                                        new FrameworkPropertyMetadata(false));

        public bool MyCustomProperty01
        {
            get => (bool)GetValue(MyCustomProperty01Property );
            set => SetValue(MyCustomProperty01Property , value);
        }

        public static readonly DependencyProperty MyCustomProperty02Property =
            DependencyProperty.Register("MyCustomProperty02",
                                        typeof(bool),
                                        typeof(myDialogView),
                                        new FrameworkPropertyMetadata(false));

        public bool MyCustomProperty02
        {
            get => (bool)GetValue(MyCustomProperty02Property );
            set => SetValue(MyCustomProperty02Property , value);
        }
    }
}

So when I start typing these dependency properties MyCustomProperty01 and MyCustomProperty01 for the window in the xaml view, intellisense looks like it is not recognizing those dependency properties. So what am I doing wrong? Could some tell me how I can achieve this with some code snippet?

CodePudding user response:

You need to registerattached for this to work.

I'm not 100% sure why, I just know it won't work with the usual dependency property.

I think it's because it's in a window tag and it's "really" a myDialogView causes the issue.

Here's an example attached property I have:

    public static readonly DependencyProperty TakeMapPictureProperty = 
            DependencyProperty.RegisterAttached(
            "TakeMapPicture",
            typeof(bool),
            typeof(MainWindow),
            new FrameworkPropertyMetadata(false
          , new PropertyChangedCallback(TakeMapPictureChanged)
        ));

    private static async void TakeMapPictureChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    }

    public static void SetTakeMapPicture(UIElement element, bool value)
    {
        element.SetValue(TakeMapPictureProperty, value);
    }
    public static bool GetTakeMapPicture(UIElement element)
    {
        return (bool)element.GetValue(TakeMapPictureProperty);
    }

And in the window tag

    local:MainWindow.TakeMapPicture="{Binding CaptureMap}"

Where you might want to use the one dependency property in several user controls or windows, you can define the attached properties in a separate class. There are a couple of ways to do this but the one I prefer looks like:

public class MainWin : DependencyObject
{
    public static readonly DependencyProperty MapFileProperty = DependencyProperty.RegisterAttached(
        "MapFile",
         typeof(string),
         typeof(MainWin),
         new FrameworkPropertyMetadata(string.Empty
             , new PropertyChangedCallback(MapFileChanged)
        ));

And that is used inside a window tag:

    local:MainWin.MapFile="{Binding Path=MapFile}"

CodePudding user response:

You are trying to set the property on the wrong element (locally/attribute syntax):

<Window ... MyCustomProperty01="True" />

Of course, Window does not have a MyCustomProperty01 property.
But myDialogView has this property.

To set this property, either use a Style:

<Window>
  <Window.Resources>
    <Style TargetType="myDialogView">
      <Setter Property="MyCustomProperty01" Value="True" />
    </Style>
  </Window.Resources>
</Window>

Or set it locally on the proper myDialogView element. But you would have to create a derived type (e.g., myExtendedDialogView), so that you can define myDialogView (the base type) as the root element.
Note how the root element is always the base type of the actual extending type: for example <Window /> of MainWindow or <UserControl /> of MyUserControl or <Page /> of MyPage or <Application /> of App.
Specify the partial class (the derived type that provides the code-behind file) using the x:Class directive on the root element:

<myDialogView x:Class="myExtendedDialogView"
              MyCustomProperty01="True">
</myDialogView >
// Define the extended class as partial (with code-behind)
// and the base class that contains the custom properties as a simple class (no code-behind)
partial class myExtendedDialogView : myDialogView
{
  public myExtendedDialogView() => InitializeComponent();
}
// Base class used as XAML root element.
// This type has no code-behind file (not partial)
class myDialogView : Window
{
  // Dependency properties
}
  • Related