Dependency Properties in User Controls

dmccric 0 Reputation points
2024-12-18T16:06:49.42+00:00

I have a simple Slider and Label user control that I load into my window and I want to change the following properties using databinding from the main window.

Slider Properties -> Value, SelectionStart, SelectionEnd (all doubles)

Label Properties -> Title (string)

I have created a dependency property for the Title property and that works fine for the Label but the slider properties have me stumped. I can change the value manually in the xaml code but not programmatically.

public static readonly DependencyProperty SelStart_Property =

DependencyProperty.Register("Set_SelStart", typeof(double), typeof(UserTest), new PropertyMetadata(0.0, OnSelStart_Changed));

// Set SELECTION START (double) property of Slider

// MODE = 1 Way (Set)

public double Set_SelStart

{

**get { return (double)GetValue(SelStart_Property); }**

**set { SetValue(SelStart_Property, value); }**

}

private static void OnSelStart_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)

{

**var User = d as UserTest;**

**User.Digit_Slider.SelectionStart = (double)e.NewValue;**

}

XAML

<Grid>

**<Grid.RowDefinitions>**

    **<RowDefinition Height="40" />**

    **<RowDefinition Height="*" />**

    **<RowDefinition Height="40" />**

**</Grid.RowDefinitions>**

**<Grid.ColumnDefinitions>**

    **<ColumnDefinition Width="100" />**

    **<ColumnDefinition Width="100" />**

**</Grid.ColumnDefinitions>**

**<Label Content="{Binding Path=Position, ElementName=userTest}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" />**

**<uc:UserTest x:Name="userTest" Position="{Binding Pos}" Set_Title="THUMB" Set_SelStart="{Binding Start}" Set_SelEnd="{Binding End}" Grid.Row="1" Margin="0,0,0,20" />**

**<Label Content="{Binding Value, ElementName=Slider1, StringFormat=\{0:D3\}}" Grid.Column="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" />**

**<Slider x:Name="Slider1" Value="50" IsSelectionRangeEnabled="True" SelectionStart="10" SelectionEnd="90" Grid.Row="1" Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Center" Maximum="100" SmallChange="1" Margin="0,45,0,24" />**

**<Button x:Name="btn_Press" Content="Press" Grid.Row="2" Margin="10,10,10,10" Click="btn_Press_Click" />**

</Grid>

I have a normal slider and label at the side of the user control and have no problem with that so the dependency properties are not right.

I have placed a breakpoint in the set / get properties and they do break but no change to the screen.

Any advice is grateful

Regards

.NET
.NET
Microsoft Technologies based on the .NET software framework.
4,007 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,804 questions
C#
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.
11,152 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Hongrui Yu-MSFT 3,645 Reputation points Microsoft Vendor
    2024-12-19T03:09:05.3466667+00:00

    Hi, @dmccric. Welcome to Microsoft Q&A. 

    You could refer to the following code to fix your problem.

    UserTest.xaml

    <Grid>
        <Slider x:Name="Digit_Slider" Value="{Binding Position,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}" Height="20"></Slider>
    </Grid>
    

    UserTest.xaml.cs

        public partial class UserTest : UserControl
        {
            public double Set_SelStart
            {
                get { return (double)GetValue(SelStart_Property); }
                set { SetValue(SelStart_Property, value); }
            }
    
            public static readonly DependencyProperty SelStart_Property = DependencyProperty.Register("Set_SelStart", typeof(double), typeof(UserTest), new PropertyMetadata(0.0, OnSelStart_Changed));
    
            private static void OnSelStart_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var User = d as UserTest;
                User.Digit_Slider.Minimum = (double)e.NewValue;
            }
    
            public double Set_SelEnd
            {
                get { return (double)GetValue(SelEnd_Property); }
                set { SetValue(SelEnd_Property, value); }
            }
    
            public static readonly DependencyProperty SelEnd_Property = DependencyProperty.Register("Set_SelEnd", typeof(double), typeof(UserTest), new PropertyMetadata(0.0, OnSelEnd_Changed));
    
            private static void OnSelEnd_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var User = d as UserTest;
                User.Digit_Slider.Maximum = (double)e.NewValue;
            }
    
            public double Position
            {
                get { return (double)GetValue(Position_Property); }
                set { SetValue(Position_Property, value); }
            }
    
            public static readonly DependencyProperty Position_Property = DependencyProperty.Register("Position", typeof(double), typeof(UserTest), new PropertyMetadata(0.0));
            public UserTest()
            {
                InitializeComponent();
            }
        }
    

    MainWindow.xaml

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
            <RowDefinition Height="40" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <Label Content="{Binding Path=Position, ElementName=userTest}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" />
        <local:UserTest x:Name="userTest" Position="{Binding Pos,Mode=TwoWay}" Set_SelStart="{Binding Start}" Set_SelEnd="{Binding End}" Grid.Row="1" Margin="0,0,0,20" />
        <Label Content="{Binding Value, ElementName=Slider1, StringFormat=\{0:D3\}}" Grid.Column="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontWeight="Bold" />
        <Slider x:Name="Slider1" Value="50" IsSelectionRangeEnabled="True" SelectionStart="10" SelectionEnd="90" Grid.Row="1" Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Center" Maximum="100" SmallChange="1" Margin="0,45,0,24" />
        <Button x:Name="btn_Press" Content="Press" Grid.Row="2" Margin="10,10,10,10" Click="btn_Press_Click" />
    </Grid>
    

    MainWindow.xaml.cs

    public partial class MainWindow : Window,INotifyPropertyChanged
    {
        private double pos;
        public double Pos { get { return pos; } set { pos = value; OnPropertyChanged(nameof(Pos)); } }
    
        private double start;
        public double Start { get { return start; } set { start = value; OnPropertyChanged(nameof(Start)); } }
    
        private double end;
    
        public double End { get { return end;} set { end = value; OnPropertyChanged(nameof(End)); } }
    
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
            Start = 1f;
            End = 100f;
        }
    
        public event PropertyChangedEventHandler? PropertyChanged;
    
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        private void btn_Press_Click(object sender, RoutedEventArgs e)
        {
            Pos = 50f;
        }
    }
    

    Not sure if you want to set the minimum value of the Slider via Set_SelStart, so in the OnSelStart_Changed method I replaced User.Digit_Slider.SelectionStart = (double)e.NewValue; with User.Digit_Slider.Minimum = (double)e.NewValue;

    In order to ensure that the Position could also sense the change when the Digit_Slider is dragged, I replaced the new PropertyMetadata(0.0, OnSelStart_Changed) method with Value="{Binding Position,Mode=TwoWay,RelativeSource={RelativeSource AncestorType=UserControl}}" to update Value

    Finally, the normal data binding in MainWindow.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    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.


Your answer

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