Listen to two (or more) properties

BitSmithy 1,771 Reputation points
2023-01-06T20:44:00.14+00:00

Hello,

I am binding TextBox to UserControl
myUserControl.DataContext = myTextBox;

myUserControl.Height should be calculated and changed every time when myTextBox.FontSize or myTextBox.FontFamily changes.

How to do such behavior. I dont wan to use any external modules, but only pure UWP.

Universal Windows Platform (UWP)
{count} votes

Accepted answer
  1. Roy Li - MSFT 32,236 Reputation points Microsoft Vendor
    2023-01-31T08:30:29.35+00:00

    Hello,

    Welcome to Microsoft Q&A!

    If you could use a UserControl as the container of the TextBox, then you could create some properties which represents TextBox.FontSize and TextBox.FontFamily . Then you could implement INotifyPropertyChanged in the UserControl. So when the custom properties are changed, you will get notified and change the Height of the TextBox.

    I've made a sample to test. I placed a TextBox in XAML as the source. Then pass it to the UserControl. The target TextBox binds to properties of the UserControl. After that, set the UserControl as the datacontext of the target TextBox

    UserControl.CS

    
     public sealed partial class MyUserControl1 : UserControl, INotifyPropertyChanged
        {
            private TextBox SourceTextBox;
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void RaisePropertyChangedEvent(string name)
            {
                if (PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
                }
                if (name.Equals("MyfontSize")||name.Equals("MyfontFamily")) 
                {
                    MyTextBoxHeight = MyTextBoxHeight + 50;
                }
            }
    
            public MyUserControl1(TextBox textBox)
            {
                this.InitializeComponent();
                SourceTextBox = textBox;
            }
    
            // fontSize property
            public double MyTextBoxHeight
            {
                get
                {
                    return SourceTextBox.Height;
                }
                set
                {
                    SourceTextBox.Height = value;
                    RaisePropertyChangedEvent("MyTextBoxHeight");
                }
            }
    
            // fontSize property
            public double MyfontSize
            {
                get
                {
                    return  SourceTextBox.FontSize; 
                }
                set
                {
                    SourceTextBox.FontSize = value;
                    RaisePropertyChangedEvent("MyfontSize");
                }
            }
            // fontfamily property
            public FontFamily MyfontFamily
            {
                get
                {
                    return SourceTextBox.FontFamily;
                }
                set
                {
                    SourceTextBox.FontFamily = value;
                    RaisePropertyChangedEvent("MyfontFamily");
                }
            }
          
        }
    

    MainPage.CS

    
     public sealed partial class MainPage : Page
        {
            public MyUserControl1 sourceControl { get; set; }
            public MainPage()
            {
                this.InitializeComponent();
    
                sourceControl = new MyUserControl1(SourceBox);
    
                TargetBox.DataContext = sourceControl;
    
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                sourceControl.MyfontSize = 50;
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                sourceControl.MyfontFamily = new FontFamily("Times New Roman");
            }
        }
    
    

    MainPage.Xaml

      <StackPanel>
            <TextBox x:Name="SourceBox" FontSize="30" FontFamily="Arial" Height="100" Width="400"/>
    
            <TextBox x:Name="TargetBox" Width="400" FontSize="{Binding MyfontSize,Mode=TwoWay}" FontFamily="{Binding MyfontFamily,Mode=TwoWay}" Height="{Binding MyTextBoxHeight,Mode=TwoWay}"/>
    
            <Button Content="ChangeSize" Click="Button_Click" />
    
            <Button Content="ChangeFont" Click="Button_Click_1" />
        </StackPanel>
    </Page>
    
    

    Thank you.


    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.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Roy Li - MSFT 32,236 Reputation points Microsoft Vendor
    2023-01-09T07:20:06.367+00:00

    Hello,

    Welcome to Microsoft Q&A!

    A possible way is that raise the propertychanged event when the FontSize property or FontFamily property of the TextBox changes. And you need to bind these two properties to the UserControl and handling the change event in UserControl. Then you could notify the UserControl to change its height after the properties are changed.

    1) Create a custom TextBox and implement INotifyPropertyChanged. Use the default TextBox style as style.
    2) Add two custom properties MyFontSize and MyFontFamily to the TextBox and we will use them later for binding.
    3) Create two custom dependency properties in the UserControl and handle the propertychanged callback for these properties.
    4) Create a HeightChange event in the UserControl which will be trigger later in the propertychanged callback.
    5) Bind these properties in XAML and set the DataContext in code-behind.
    6) As soon as the DataContext has been set, the propertychanged callback of the dependency properties will be invoked. The HeightChange event will be raised, and the height will be changed.

    Here is the demo I made. you could refer to it. Please note: when you click the button, you will set the DataContext of the UserControl, this will also trigger the property changed callback. The height change is hard coded in the demo, and you need to change it to fix your own scneario.

    NewTextBox.cs

     public class NewTextBox:TextBox,INotifyPropertyChanged  
        {  
            public NewTextBox()  
            {  
                this.DefaultStyleKey= typeof(TextBox);  
            }  
    
            public double MyFontSize   
            {  
                get   
                {  
                    return this.FontSize;  
                }  
                set  
                {  
                    this.FontSize = value;  
                    RaisePropertyChangedEvent("MyFontSize");  
                }  
            }  
    
            public FontFamily MyFontFamily  
            {  
                get  
                {  
                    return this.FontFamily;  
                }  
                set  
                {  
                    this.FontFamily = value;  
                    RaisePropertyChangedEvent("MyFontFamily");  
                }  
            }  
    
            public event PropertyChangedEventHandler PropertyChanged;  
    
            public void RaisePropertyChangedEvent(string name)   
            {  
                if (PropertyChanged != null)  
                {  
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));  
                }  
            }  
        }  
    

    UserControl.cs

       public sealed partial class MyUserControl1 : UserControl  
        {  
            //custom event, used in the propertychange callback.  
            public delegate void HeightChangeHandler();  
            public event HeightChangeHandler OnHeightChange;  
    
            public MyUserControl1()  
            {  
                this.InitializeComponent();  
                this.OnHeightChange += MyUserControl1_OnHeightChange;  
            }  
    
    
            private void MyUserControl1_OnHeightChange()  
            {  
                //check value and change height  
                var str = this.MyfontFamily;  
                var size = this.MyfontSize;  
                if (size.Equals(55))  
                {  
                    this.Height = 200;  
                }  
                else   
                {  
                    this.Height = 100;  
                }  
    
            }  
    
    
            // fontSize property  
            public double MyfontSize  
            {  
                get { return (double)GetValue(MyfontSizeProperty); }  
                set { SetValue(MyfontSizeProperty, value); }  
            }  
    
            // Using a DependencyProperty as the backing store for MyfontSize.  This enables animation, styling, binding, etc...  
            public static readonly DependencyProperty MyfontSizeProperty =  
                DependencyProperty.Register("MyfontSize", typeof(double), typeof(MyUserControl1), new PropertyMetadata(null, new PropertyChangedCallback(onfontsizeChanged)));  
    
    
            private static void onfontsizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
            {  
                MyUserControl1 control = d as MyUserControl1;  
    
                if (!control.MyfontSize.Equals(0))  
                {  
                    if (control.OnHeightChange != null)  
                    {  
                        control.OnHeightChange();  
                    }  
                }  
            }  
    
            // fontfamily property  
            public FontFamily MyfontFamily  
            {  
                get { return (FontFamily)GetValue(MyfontFamilyProperty); }  
                set { SetValue(MyfontFamilyProperty, value); }  
            }  
    
            // Using a DependencyProperty as the backing store for MyfontFamily.  This enables animation, styling, binding, etc...  
            public static readonly DependencyProperty MyfontFamilyProperty =  
                DependencyProperty.Register("MyfontFamily", typeof(FontFamily), typeof(MyUserControl1), new PropertyMetadata(null, new PropertyChangedCallback(onfontfamilyChanged)));  
    
            private static void onfontfamilyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
            {  
                MyUserControl1 control = d as MyUserControl1;  
    
                if (control.MyfontFamily != null )   
                {  
                    if (control.OnHeightChange != null)  
                    {  
                        control.OnHeightChange();  
                    }  
                }  
            }  
        }  
    

    UserControl.Xaml

     <Grid **Background="Yellow">  
    
        </Grid>  
    

    MainPage.Xaml

       <StackPanel Orientation="Vertical">  
            <local:NewTextBox x:Name="MyTextBox" Text="abcd" MyFontSize="85" MyFontFamily="Times New Roman"/>  
    
    
            <local:MyUserControl1 x:Name="MyUserControl"  Width="500" Height="500" MyfontFamily="{Binding FontFamily,Mode=OneWay}" MyfontSize="{Binding FontSize,Mode=OneWay}"/>  
    
            <Button Content="SetDatContext" Click="Button_Click"/>  
            <Button Content="ChangeSize" Click="Button_Click_1"/>  
        </StackPanel>  
    

    MainPage.CS

      public MainPage()  
            {  
                this.InitializeComponent();  
            }  
            private void Button_Click(object sender, RoutedEventArgs e)  
            {  
                MyUserControl.DataContext = MyTextBox;  
            }  
    
            private void Button_Click_1(object sender, RoutedEventArgs e)  
            {  
                MyTextBox.FontSize = 55;  
            }  
    

    Thank you.


    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.

    1 person found this answer helpful.
    0 comments No comments