wpf_ how to use binding outside of controls

KarlOKeeffe 20 Reputation points
2023-06-27T06:47:09.4433333+00:00

Hello, I am a new programmer, using XAML to draw the interface is, I defined a custom control to TextBox encapsulated Label and Unit, but I can't get the value when binding the textbox, I don't know where the error is, here's the code.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApp1">
    <Style TargetType="{x:Type local:MyControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyControl}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="50" Width="3*" />
                            <ColumnDefinition Width="5*" />
                            <ColumnDefinition MinWidth="28" Width="2*"  />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="0" Text="{Binding Label}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                        <ContentPresenter Grid.Column="1" Height="20" ContentSource="InnerContent"/>
                        <TextBlock Grid.Column="2" Text="{Binding Unit}" Margin="5 0 0 0"   VerticalAlignment="Center"  HorizontalAlignment="Left"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
[ContentProperty("Content")] 
public class MyControl : Control
{
    static MyControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
    }
    #region DataContext
    public string Label
    {
        get { return (string)GetValue(LabelProperty); }
        set { SetValue(LabelProperty, value); }
    }
    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));

    public string Unit
    {
        get { return (string)GetValue(UnitProperty); }
        set { SetValue(UnitProperty, value); }
    }
    public static readonly DependencyProperty UnitProperty = DependencyProperty.Register("Unit", typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));
    #endregion
}

Here is the code to use the control

<Window.DataContext>
    <local:MainViewModel x:Name="mydata"/>
</Window.DataContext>
<local:MyControl Label="Approved voltage" Unit="V" Height="30" Width="200" HorizontalAlignment="Left" VerticalAlignment="Top">
    <TextBox Text="{Binding ElementName=mydata, Path=InputValue,Mode=TwoWay}" />
</local:MyControl>
<TextBlock Text="{Binding ElementName=mydata, Path=InputValue,StringFormat=[{0}]}" Height="30" Width="200"  HorizontalAlignment="Left" VerticalAlignment="Top"/>

I can't get to the value of InputValue, maybe I'm using the wrong one, please advise.

Developer technologies | Windows Presentation Foundation
Developer technologies | XAML
Developer technologies | XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
{count} votes

Answer accepted by question author
  1. Hui Liu-MSFT 48,711 Reputation points Microsoft External Staff
    2023-06-27T07:46:26.9433333+00:00

    Hi,@Karl Albright. Welcome Microsoft Q&A. You could refer to the following code. You can also refer here for more details.

    <Style TargetType="{x:Type local:MyControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:MyControl}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MinWidth="50" Width="5*" />
                                <ColumnDefinition Width="5*" />
                                <ColumnDefinition MinWidth="28" Width="2*"  />
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{TemplateBinding Label}" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="10"  Foreground="Black" />
                           
                            <ContentPresenter Grid.Column="1" Height="20" ContentSource="{TemplateBinding Content}"/>
                            <TextBlock Grid.Column="2" Text="{TemplateBinding Unit}" Margin="5 0 0 0"   VerticalAlignment="Center"  HorizontalAlignment="Left" FontSize="20" Foreground="Black"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    MyControl:

      [ContentProperty("Content")] 
        public class MyControl : Control
        {
            static MyControl()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
            }
            public string Label
            {
                get { return (string)GetValue(LabelProperty); }
                set { SetValue(LabelProperty, value); }
            }
            public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));
    
            public string Unit
            {
                get { return (string)GetValue(UnitProperty); }
                set { SetValue(UnitProperty, value); }
            }
            public static readonly DependencyProperty UnitProperty = DependencyProperty.Register("Unit", typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));
            public object Content
            {
                get { return GetValue(ContentProperty); }
                set { SetValue(ContentProperty, value); }
            }
    
            public static readonly DependencyProperty ContentProperty =
                DependencyProperty.Register("Content", typeof(object), typeof(MyControl), new PropertyMetadata(null));
        }
    

    MainWindow.xaml:

     <Window.DataContext>
            <local:MainViewModel />
        </Window.DataContext>
        
        <StackPanel>
            <local:MyControl Label="Approved voltage" Unit="V" Height="30" Width="200" HorizontalAlignment="Left" VerticalAlignment="Top">
                <local:MyControl.Content>
                       <TextBox Text="{Binding Path=InputValue,Mode=TwoWay}" />
                </local:MyControl.Content>
                 
            </local:MyControl>
            
            <TextBlock Text="{Binding  Path=InputValue,StringFormat=[{0}]}" Height="30" Width="200"  HorizontalAlignment="Left" VerticalAlignment="Top"/>
        </StackPanel>
    
    
    

    MainViewModel:

    public class MainViewModel
        {
            public MainViewModel() { }
            public string InputValue { get; set; } = "0.1";
        }
    

    The result:

    User's image


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.