locked
dependency property in user control. Value is blank. RRS feed

  • Question

  • I have a user control with a TextBox.  The Text property of the TextBox is bound to a dependency property.  When a value is entered into the TextBox and you click a button in the user control, the dependency property value is set correctly.  But when you enter that same text, then click a button outside of the user control, the dependency property value remains empty.

    I assume this has to do with the TextBox losing focus.  How to make it so the dependency property bound to a textbox always matches the value of the Text property of that TextBox?

    thanks,

    here is the user control:


    <UserControl x:Class="UserControlDemo.CustNameControl"
                 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:local="clr-namespace:UserControlDemo"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
          <RowDefinition Height="auto"></RowDefinition>
          <RowDefinition Height="auto"></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="Customer name"/>
          <TextBox x:Name="tbCustName" Width="100" Text="{Binding CustName}"></TextBox>
        </StackPanel>
        <Button x:Name="butOk" Grid.Row="1" Click="butOk_Click">OK</Button>
                
        </Grid>
    </UserControl>

    the code behind of the user control that declares the dependency property:

    namespace UserControlDemo
    {
      /// <summary>
      /// Interaction logic for CustNameControl.xaml
      /// </summary>
      public partial class CustNameControl : UserControl
      {
    
        public string CustName
        {
          get { return (string)GetValue(CustNameProperty); }
          set { SetValue(CustNameProperty, value); }
        }
    
        public static readonly DependencyProperty CustNameProperty =
        DependencyProperty.Register("CustName", typeof(string),
        typeof(CustNameControl), new PropertyMetadata(""));
    
    
        public CustNameControl()
        {
          InitializeComponent();
          LayoutRoot.DataContext = this;
        }
    
        private void butOk_Click(object sender, RoutedEventArgs e)
        {
          Debug.Print("butOk_Click event.");
          Debug.Print("Custname value:" + this.CustName);
        }
      }
    }

    a window that uses the user control:

    <Window x:Class="UserControlDemo.CustNameWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:uc="clr-namespace:UserControlDemo"
            xmlns:local="clr-namespace:UserControlDemo"
            mc:Ignorable="d"
            Title="CustNameWindow" Height="300" Width="300">
        <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="auto"></RowDefinition>
          <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
    
        <Menu Grid.Row="0" x:Name="menu1" HorizontalAlignment="Left"
              VerticalAlignment="Top">
            <MenuItem Header="GetCustName" Click="MenuItem_Click"></MenuItem>
            <MenuItem Header="Exit" Click="MenuItem_Click"></MenuItem>
          </Menu>
          
        <uc:CustNameControl Grid.Row="1"  x:Name="CustNameControl1"/>
      </Grid>
    </Window>

    and the code behind of the window:

    namespace UserControlDemo
    {
      /// <summary>
      /// Interaction logic for CustNameWindow.xaml
      /// </summary>
      public partial class CustNameWindow : Window
      {
        public CustNameWindow()
        {
          InitializeComponent();
        }
    
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
          string itemText = null;
          if (sender is MenuItem)
            itemText = (sender as MenuItem).Header as string;
    
          if (itemText == "GetCustName")
          {
            Debug.Print("GetCustName menu item click handler.");
            Debug.Print("CustName is:" + CustNameControl1.CustName);
            Debug.Print("tbCustName.Text:" + CustNameControl1.tbCustName.Text);
          }
    
          else if (itemText == "Exit")
          {
            this.Close();
          }
        }
    
      }
    }



    Monday, May 16, 2016 11:42 PM

Answers

  • Hi Steve Richter,

    >>"Clicking a menu item within the user control does not cause the textbox to lose focus. Which means the dependency property does not show the correct value."

    Yes, that is right. There is a property named UpdateSourceTrigger for binding. It define the way how to determine the timing of binding source updates. The default value for TextBox is LostFocus. Change it to PropertyChanged will solve your problem.

    <TextBox Text="{Binding CustName,UpdateSourceTrigger=PropertyChanged}" />
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Steve Richter Tuesday, May 17, 2016 10:44 AM
    Tuesday, May 17, 2016 7:26 AM

All replies

  • I see that the problem with the dependency property not being set has nothing to do with controls outside of the user control. When I add a menu to the user control the same problem occurs. Clicking a menu item within the user control does not cause the textbox to lose focus. Which means the dependency property does not show the correct value.

    <UserControl x:Class="UserControlDemo.CustNameControl"
                 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:local="clr-namespace:UserControlDemo"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
          <RowDefinition Height="auto"></RowDefinition>
          <RowDefinition Height="auto"></RowDefinition>
          <RowDefinition Height="auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Menu Focusable="True" Grid.Row="0">
          <MenuItem Header="Test" Click="MenuItem_Click"></MenuItem>
          <MenuItem Header="Exit" Click="MenuItem_Click"></MenuItem>
        </Menu>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
          <TextBlock Text="Customer name"/>
          <TextBox x:Name="tbCustName" Width="100"
                   GotFocus="tbCustName_GotFocus" LostFocus="tbCustName_LostFocus"
                   Text="{Binding CustName}"></TextBox>
        </StackPanel>
        <Button x:Name="butOk" Grid.Row="2" Click="butOk_Click">OK</Button>
                
        </Grid>
    </UserControl>
    
    namespace UserControlDemo
    {
      /// <summary>
      /// Interaction logic for CustNameControl.xaml
      /// </summary>
      public partial class CustNameControl : UserControl
      {

        public string CustName
        {
          get { return (string)GetValue(CustNameProperty); }
          set { SetValue(CustNameProperty, value); }
        }

        public static readonly DependencyProperty CustNameProperty =
        DependencyProperty.Register("CustName", typeof(string),
        typeof(CustNameControl), new PropertyMetadata(""));


        public CustNameControl()
        {
          InitializeComponent();
          LayoutRoot.DataContext = this;
        }

        private void butOk_Click(object sender, RoutedEventArgs e)
        {
          Debug.Print("butOk click handler.");
          Debug.Print("Custname value:" + this.CustName);
        }

        private void tbCustName_GotFocus(object sender, RoutedEventArgs e)
        {
          Debug.Print("tbCustName. Got focus.");
        }

        private void tbCustName_LostFocus(object sender, RoutedEventArgs e)
        {
          Debug.Print("tbCustName. Lost focus.");
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
          string itemText = null;
          if (sender is MenuItem)
            itemText = (sender as MenuItem).Header as string;

          if (itemText == "Test")
          {
            Debug.Print("menuItem click handler.");
            Debug.Print("Custname value:" + this.CustName);
          }
        }

      }


    Tuesday, May 17, 2016 4:01 AM
  • Hi Steve Richter,

    >>"Clicking a menu item within the user control does not cause the textbox to lose focus. Which means the dependency property does not show the correct value."

    Yes, that is right. There is a property named UpdateSourceTrigger for binding. It define the way how to determine the timing of binding source updates. The default value for TextBox is LostFocus. Change it to PropertyChanged will solve your problem.

    <TextBox Text="{Binding CustName,UpdateSourceTrigger=PropertyChanged}" />
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Steve Richter Tuesday, May 17, 2016 10:44 AM
    Tuesday, May 17, 2016 7:26 AM