none
用于Content的类如何实现GetHashCode()方法? RRS feed

  • 问题

  • <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Loaded="Window_Loaded" SizeToContent="WidthAndHeight">
        <Window.Resources>
            <DataTemplate x:Key="editTemplate" DataType="MyClass">
                <TextBox Name="nameElement" Text="{Binding Path=Name}" Width="130" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" />
            </DataTemplate>
        </Window.Resources>
        <DockPanel>
            <DockPanel >
                <WrapPanel Name="controllersPanel">
                    <ContentControl ContentTemplate="{DynamicResource editTemplate}" x:Name="controllerInfoBox" Width="100" />
                </WrapPanel>
                <Button Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
            </DockPanel>
        </DockPanel>
    </Window>
    

    上面在窗体内放了两个元素,一个用TextBox显示对象的ContentControl,另一个是按钮。

    public partial class MainWindow : Window
    {
    	public static readonly MyClass MyClass = new MyClass { Name = "MyClass" };
    
    	public MainWindow()
    	{
    		InitializeComponent();
    	}
    
    	private void Window_Loaded(object sender, RoutedEventArgs e)
    	{
    		controllerInfoBox.Content = MyClass;
    	}
    
    	private void button1_Click(object sender, RoutedEventArgs e)
    	{
    		MyClass.Name = "abc";
    		//controllerInfoBox.Content = null;
    		controllerInfoBox.Content = MyClass;
    	}
    }
    
    public class MyClass
    {
    	public string Name { get; set; }
    
    }
    

    点击按钮后,重设MyClass.Name。光重设是不会自动反应到界面上的,于是我再赋值一次。可是界面还是不会变化的,除非先=null。

    我想应该是Content set方法里有比较,如果旧值等于新值,就不赋值了。所以我决定覆盖MyClass的equals方法。按照微软的建议“每次实现 Equals 方法时都实现 GetHashCode 方法”,我再试着提供GetHashcode方法。但是我看到http://cnn237111.blog.51cto.com/2359144/588694 说

    对于任何一个对象A,A.GetHashCode()必须是一个实例不变式(invariant)。即不管在A上调用什么方法,A.GetHashCode()都必须总是返回相同的值。这可以确保放在“散列桶”中的对象总是位于正确的“散列桶”中。——(1)

    这我就犯难了,Equals是根据Name比较的,Name变equals结果也变。两个对象equals相等,gethashcohe也要相等,但又违反了(1)。

    请问我应该怎么办?



    2011年12月29日 8:56

答案

  • 你这个现象就是我上次所说的,如果你在C#代码中更改绑定的数据源的值,你的数据源类型必须实现了 INotifyPropertyChanged 接口,然后他会才自动更新到的绑定界面上。所以你只要让 MyClass 实现了 INotifyPropertyChanged  接口就可以了:

      public class MyClass : INotifyPropertyChanged
      {
        private string _name;
        public string Name
        {
          get { return _name; }
          set
          {
            _name = value;
            if (PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs("Name"));
          }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
      }
    


     

    本身你的这个对象没有变,他的HashCode当然不会变,至于你重写Equals方法,是否要让他们相同,这个你可以控制。但是对于你的这个简单的问题,没有必要这么复杂。

    如果即使你的MyClass没有实现接口,也可以通过下面的方法来让这个绑定强制更新的:

        private void button1_Click(object sender, RoutedEventArgs e)
        {
          MyClass.Name = "abc";
          //controllerInfoBox.Content = null;
          //controllerInfoBox.Content = MyClass;
    
          TextBox textBox = FindVisualChildByName<TextBox>(controllerInfoBox, "nameElement");
          BindingExpression binding = BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty);
          binding.UpdateTarget();
        }
    
        public T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
        {
          for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
          {
            var child = VisualTreeHelper.GetChild(parent, i);
            string controlName = child.GetValue(Control.NameProperty) as string;
            if (controlName == name)
              return child as T;
            else
            {
              T result = FindVisualChildByName<T>(child, name);
              if (result != null)
                return result;
            }
          }
          return null;
        }

     

    Sincerely,
    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2011年12月30日 9:50
    版主