开发者

WPF Dependency Property Question

开发者 https://www.devze.com 2023-02-11 16:58 出处:网络
I\'m new to WPF, and I\'m trying to do what I thought would be a simple task - display the value of a field in my business object as it changes during my program. I know how to \"force\" it to change

I'm new to WPF, and I'm trying to do what I thought would be a simple task - display the value of a field in my business object as it changes during my program. I know how to "force" it to change by manually changing the TextBox.Text property in C#, but as I'm learning WPF I want to do it the "right" way, and that means databinding.

Question #1: As far as I understand it, my choice is to either use a DependencyProperty or implement INotifyPropertyChanged in my business object, right?

Question #2: Here is a generic version of my code in which I attempted to go the DependencyProperty route.

Markup:

Button x:Name="nextButton" Content="Click"  Grid.Row="2" Click="nextButton_Click" />
TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Source=myTest, Path=Name, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"/>

Code-Behind:

namespace DependencyTest2
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        private int i;

        private TestSphere myTest;

        public MainWindow()
        {
            InitializeComponent();

            i = 0;

            myTest = new TestSphere();
        }

        private void nextButton_Click(object sender, RoutedEventArgs e)
        {
            switch (i)
            {
                case 0:
                    myTest.Name = "string1";
                    break;
                case 1:
                    myTest.Name = "string2";
                    break;
                case 2:
                    myTest.Name = "string3";
                    break;
            }

            i++;
        }
    }

    class TestSphere : DependencyObject
    {

        public string Name
        {
            get { return (string)GetValue(NameProperty); }
            set { SetValue(NameProperty, value); }
        }

        public static readonly DependencyProperty NameProperty =
            DependencyProperty.Register("Name", typeof(string), typeof(TestSphere));


        public TestSphere()
        {
            Name开发者_运维技巧 = "default";
        }
    }
}

When I run the program, nothing appears in text box, even though the bound property has a value - is there something else I need to do to alert the binding that the source value has changed? I thought that using a DependencyProperty as the source would take care of that, but then again, I'm a WPF rookie. Thanks!

  • Steve

Ok, I tried to implement INotifyPropertyChanged using a wrapper class I found on codeproject as follows:


    class TestSphere : NotifyProperyChangedBase
    {
        private string _Name;

        public string Name
        {
            get { return _Name; }
            set 
            {
                this.CheckPropertyChanged("Name", ref _Name, ref value);
            }
        }

        public TestSphere()
        {
            Name = "default";
        }
    }

    public abstract class NotifyProperyChangedBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        #region methods
        protected bool CheckPropertyChanged(string propertyName, ref T oldValue, ref T newValue)
        {
            if (oldValue == null && newValue == null)
            {
                return false;
            }

            if ((oldValue == null && newValue != null) || !oldValue.Equals((T)newValue))
            {
                oldValue = newValue;
                FirePropertyChanged(propertyName);
                return true;
            }

            return false;
        }

        protected void FirePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

Here is my new Markup, too:


    Grid Name="myGrid">
        Grid.RowDefinitions>
            RowDefinition Height="30"/>
            RowDefinition Height="30"/>
            RowDefinition Height="30"/>
            RowDefinition Height="*"/>
        /Grid.RowDefinitions>
        Label x:Name="myLabel" Grid.Row="0" Foreground="Black"  />
        Button x:Name="nextButton" Content="Click"  Grid.Row="2" Click="nextButton_Click" />
        TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Path=myTest.Name}"/>
    /Grid>

I also added the line myGrid.DataContext = myTest; to 'public MainWindow()' immediately after I instantiate myTest. When I step through the resulting program, the value of this.PropertyChanged always evaluates to null, so that the PropertyChanged even never fires. Sorry in advance for what must be a really noob question.

  • Steve


You should only need to implement INotifyPropertyChanged on the TestSphere class, not DependencyObject. As you update the value, call PropertyChanged(this, new PropertyChangedEventArgs("Name")).

Second, you need to set the DataContext for the window in your code-behind. Lets say you used this in your XAML for the root grid element:

<Grid Name="MainForm">

Then in your code-behind, you'd do this:

MainForm.DataContext = this;

Finally, change the myTest property to public, and the binding in your XAML should then only need to be

Text="{Binding Path=myTest.Name}"
0

精彩评论

暂无评论...
验证码 换一张
取 消