Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVVM数据绑定未更新_C#_Wpf - Fatal编程技术网

C# MVVM数据绑定未更新

C# MVVM数据绑定未更新,c#,wpf,C#,Wpf,我有一个小的WPF应用程序,我开始学习MVVM数据绑定模式。我有一个空的文本框,我把它绑定到“FirstName”上,但是当我运行代码时,它并没有更新。我有一个ObserveObject类,它从INotifyPropertyChanged类继承来检查属性是否已更新。当我运行代码时,属性确实采用了正确的值,但是UI从不更新 我的代码如下 MainWindow.xaml <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FirstName

我有一个小的WPF应用程序,我开始学习MVVM数据绑定模式。我有一个空的文本框,我把它绑定到“FirstName”上,但是当我运行代码时,它并没有更新。我有一个ObserveObject类,它从INotifyPropertyChanged类继承来检查属性是否已更新。当我运行代码时,属性确实采用了正确的值,但是UI从不更新

我的代码如下

MainWindow.xaml

<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FirstName}" VerticalAlignment="Center" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="16" Margin="20,20,0,20" Width="132"></TextBox>
Person.cs

class Person:ObservableObject
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }

        set
        {
            _firstName = value;
            RaisePropertyChanged("FirstName");
        }
    }
}
MainViewModel.cs

class MainViewModel:ObservableObject
{
    List<Person> pList = new List<Person>();
    public MainViewModel()
    {
        pList = new List<Person>()
        {
            new Person() {FirstName="Craig"}
        };
        Init();
    }

    public void Init()
    {
        var li = pList.FirstOrDefault();

    }

}
class MainViewModel:ObserveObject
{
List pList=新列表();
公共主视图模型()
{
pList=新列表()
{
新人(){FirstName=“Craig”}
};
Init();
}
公共void Init()
{
var li=pList.FirstOrDefault();
}
}
OnservableObject.cs

[Serializable]
public abstract class ObservableObject : INotifyPropertyChanged, IDisposable
{
    #region Constructor

    protected ObservableObject()
    {
    }

    #endregion Constructor

    #region DisplayName

    /// <summary>
    /// Returns the user-friendly name of this object.
    /// Child classes can set this property to a new value,
    /// or override it to determine the value on-demand.
    /// </summary>
    public virtual string DisplayName { get; protected set; }

    #endregion DisplayName

    #region INotifyPropertyChanged Members

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        this.PropertyChanged?.Invoke(this, e);
    }

    protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
    {
        var propertyName = PropertySupport.ExtractPropertyName(propertyExpresssion);
        this.RaisePropertyChanged(propertyName);
    }

    protected void RaisePropertyChanged(String propertyName)
    {
        VerifyPropertyName(propertyName);
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Members

    #region Debugging Aides

    /// <summary>
    /// Warns the developer if this object does not have
    /// a public property with the specified name. This
    /// method does not exist in a Release build.
    /// </summary>
    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real,
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }
    }

    /// <summary>
    /// Returns whether an exception is thrown, or if a Debug.Fail() is used
    /// when an invalid property name is passed to the VerifyPropertyName method.
    /// The default value is false, but subclasses used by unit tests might
    /// override this property's getter to return true.
    /// </summary>
    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    #endregion Debugging Aides

    #region IDisposable Members

    /// <summary>
    /// Invoked when this object is being removed from the application
    /// and will be subject to garbage collection.
    /// </summary>
    public void Dispose()
    {
        this.OnDispose();
    }

    /// <summary>
    /// Child classes can override this method to perform
    /// clean-up logic, such as removing event handlers.
    /// </summary>
    protected virtual void OnDispose()
    {
    }



    /// <summary>
    /// Useful for ensuring that ViewModel objects are properly garbage collected.
    /// </summary>
    ~ObservableObject()
    {
        string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
        Debug.WriteLine(msg);
    }



    #endregion IDisposable Members
}
[可序列化]
公共抽象类ObserveObject:INotifyPropertyChanged,IDisposable
{
#区域构造函数
受保护的可观察对象()
{
}
#端域构造函数
#区域显示名
/// 
///返回此对象的用户友好名称。
///子类可以将此属性设置为新值,
///或覆盖它以按需确定值。
/// 
公共虚拟字符串DisplayName{get;protected set;}
#endregion显示名称
#区域INotifyProperty更改成员
[字段:非序列化]
公共事件属性更改事件处理程序属性更改;
PropertyChanged上受保护的虚拟无效(PropertyChangedEventArgs e)
{
this.PropertyChanged?.Invoke(this,e);
}
受保护的void RaisePropertyChanged(表达式属性Expression)
{
var propertyName=PropertySupport.ExtractPropertyName(PropertyExpression);
this.RaisePropertyChanged(propertyName);
}
受保护的void RaisePropertyChanged(字符串propertyName)
{
验证propertyName(propertyName);
OnPropertyChanged(新PropertyChangedEventArgs(propertyName));
}
#endregion InotifyProperty更改成员
#区域调试助手
/// 
///如果此对象没有
///具有指定名称的公共属性。此
///方法在发布版本中不存在。
/// 
[有条件的(“调试”)]
[调试步骤至]
public void VerifyPropertyName(字符串propertyName)
{
//验证属性名称是否与实数匹配,
//此对象的公共、实例属性。
if(TypeDescriptor.GetProperties(此)[propertyName]==null)
{
string msg=“无效的属性名称:”+propertyName;
if(this.ThrowOnInvalidPropertyName)
抛出新异常(msg);
其他的
调试失败(msg);
}
}
/// 
///返回是否引发异常,或者是否使用了Debug.Fail()
///将无效的属性名称传递给VerifyPropertyName方法时。
///默认值为false,但单元测试使用的子类可能会
///重写此属性的getter以返回true。
/// 
受保护的虚拟bool ThrowOnInvalidPropertyName{get;private set;}
#端域调试助手
#区域IDisposable成员
/// 
///从应用程序中删除此对象时调用
///并将接受垃圾收集。
/// 
公共空间处置()
{
this.OnDispose();
}
/// 
///子类可以重写此方法以执行
///清理逻辑,例如删除事件处理程序。
/// 
受保护的虚拟空间OnDispose()
{
}
/// 
///用于确保ViewModel对象被正确垃圾收集。
/// 
~observeObject()
{
string msg=string.Format(“{0}({1})({2})已完成”,this.GetType().Name,this.DisplayName,this.GetHashCode());
Debug.WriteLine(msg);
}
#endregion IDisposable成员
}
PropertySupport.cs

public static class PropertySupport
{
    public static String ExtractPropertyName<T>(Expression<Func<T>> propertyExpresssion)
    {
        if (propertyExpresssion == null)
        {
            throw new ArgumentNullException("propertyExpresssion");
        }

        var memberExpression = propertyExpresssion.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpresssion");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
        {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpresssion");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic)
        {
            throw new ArgumentException("The referenced property is a static property.", "propertyExpresssion");
        }

        return memberExpression.Member.Name;
    }
}
公共静态类属性支持
{
公共静态字符串ExtractPropertyName(表达式PropertyExpression)
{
if(PropertyExpression==null)
{
抛出新ArgumentNullException(“PropertyExpression”);
}
var memberExpression=propertyExpression.Body作为memberExpression;
if(memberExpression==null)
{
抛出新ArgumentException(“表达式不是成员访问表达式。”,“PropertyExpression”);
}
var property=memberExpression.Member作为PropertyInfo;
if(属性==null)
{
抛出新ArgumentException(“成员访问表达式不访问属性。”,“PropertyExpression”);
}
var getMethod=property.getMethod(true);
if(getMethod.IsStatic)
{
抛出新ArgumentException(“引用的属性是静态属性。”,“PropertyExpression”);
}
返回memberExpression.Member.Name;
}
}

您应该在MainViewModel中设置属性CurrentPerson或类似的内容。CurrentPerson应该是您的pList的第一个条目。然后可以绑定到CurrentPerson.FirstName。

您正在尝试将模型的属性直接绑定到UI。 想想你将要绑定到文本框的内容。您有一个Person列表,您可以从中将所选Person的FirstName属性绑定到文本框。从这个意义上讲,在ViewModel中创建SelectedPerson属性,并将SelectedPerson.FirstName绑定到文本框,这样就可以工作了

将以下属性添加到viewmodel

private Person _selectedPerson;
    public Person SelectedPerson
    {
        get { return _selectedPerson; }

        set
        {
            _selectedPerson= value;
            RaisePropertyChanged("SelectedPerson");
        }
    }
并尝试在XAML中绑定如下内容

<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding SelectedPerson.FirstName}" VerticalAlignment="Center" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="16" Margin="20,20,0,20" Width="132"></TextBox>

MainViewModel没有名为
FirstName
的属性。事实上,它没有任何财产

如果将
pList
定义为公共属性:

或者,您可以添加一个
Person
属性来返回va
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding SelectedPerson.FirstName}" VerticalAlignment="Center" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="16" Margin="20,20,0,20" Width="132"></TextBox>
class MainViewModel : ObservableObject
{
    public List<Person> pList { get; }

    public MainViewModel()
    {
        pList = new List<Person>()
        {
            new Person() {FirstName="Craig"}
        };
    }
}
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding pList[0].FirstName}" />