rbasniak
rbasniak

Reputation: 4974

WPF see design time binds in UserlControl without MVVM

I'm designing a new UserControl for my project and it doesn't use MVVM, because I want to bind its properties directly on the parent XAML. So I have a bunch of dependency properties and my binds are like this: Text="{Binding Title, ElementName=ThisControl}". All of them works at run time, but I really can't get it to work in design time.

I've seen many solutions here at SO, but all of them are for when you have the binds to a ViewModel property. '

I tried setting up their initial value on the properties themselves and on the constructor, but they do not show in design time. Is there any way to do that?

-- UPDATE --

Here's an example of a UserControl

--XAML

<UserControl x:Class="QualityChecker.Client.UserInterface.Pages.QuickAudit.Controls.InfoCard"
             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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             TextElement.Foreground="{DynamicResource MaterialDesignBody}"
             TextElement.FontWeight="Regular"
             TextElement.FontSize="13"
             TextOptions.TextFormattingMode="Ideal" 
             TextOptions.TextRenderingMode="Auto"   
             Background="{DynamicResource MaterialDesignPaper}"
             FontFamily="{DynamicResource MaterialDesignFont}"
             mc:Ignorable="d" 
             Name="ThisControl"
             d:DesignHeight="450" d:DesignWidth="800">
    <materialDesign:Card Width="350" Margin="8 2 4 16" Height="180">
        <Grid VerticalAlignment="Stretch">
            ...
            <TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8" Text="{Binding Title, ElementName=ThisControl}"></TextBlock>
             ...
         </Grid>
    </materialDesign:Card>
</UserControl>

-- .cs

public CustomUserControl()
{
    Title = "My Initial value"
}

public string Title
{
    get => (string)GetValue(TitleProperty);
    set => SetValue(TitleProperty, value);
}
public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register(nameof(Title), typeof(string),
    typeof(InfoCard), new FrameworkPropertyMetadata("Initial Value"));

Upvotes: 1

Views: 175

Answers (2)

DRapp
DRapp

Reputation: 48139

The following two samples I have offered in the past might help.

One sample custom user control, 3 dependency properties

Another for a customized button

To visually get what you are looking for WHILE IN DESIGN TIME is done with control templates and doing TemplateBinding for the parts in question.

I think the first example would be a better match via dependency properties, and in this one, I offer 3 different control template layouts, so you can pick whichever one works best for you.

The second shows begin-to-end on for a customized button.

The premise is that your custom control is derived from a given known control, even if derived from "User Control" and you have all your extra properties. Then you define a control template BASED-ON YOUR custom control type, not the generic "UserControl". The based on allows the XAML to properly detect the custom properties that are available that you want to expose in your final output of the control. Then, by setting a style for your control based on the control template, each time you put onto a form, it will show values set at design-time.

If you define a

<UserControl .. properties you expect... >

but don't do via

   <xmlRefNamespaceToYourClass:YourCustomClass … properties will now be visible … >

you wont see your expected properties to expose for display.

Each of the respective samples work and are pretty well commented on how/where things go and why.

Upvotes: 1

Mark Feldman
Mark Feldman

Reputation: 16119

I don't think this is going to to work the way you want it to. The problem is that designer never creates an instance of the class you are editing, only its child classes (and even then, only the ones that have already been successfully compiled). It also doesn't instantiate static code, so the DPs never get created either. The reason data binding works is because again, you're not binding anything to the class itself, you're binding its child controls to the design data.

There are workarounds, like explicitly creating an instance of the class and setting it as it's own design-time ddata context with d:DataContext, but they're really messy and will mess with data-bindings higher up the logical tree. Best thing to do is place a copy of your control in a parent window while you're designing and visualize it that way.

Upvotes: 1

Related Questions