UserControl命令修改属性

时间:2019-09-23 18:27:10

标签: wpf vb.net data-binding wpf-controls

在用户控件中,我试图获取用于修改属性的命令。我有一个IncrementValueCommand和一个Value属性,我想在单击按钮时增加它们。按钮的Command绑定到IncrementValueCommand,而Content绑定到Value属性。

我尝试了两种方法来做到这一点,在两种情况下,Button都不显示Value递增。.

第一种方法:价值的依存属性

XAML:

<UserControl x:Class="UserControl1"
             x:Name="root"
             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:WpfApp1"
             mc:Ignorable="d"
             d:DesignHeight="100"
             d:DesignWidth="200"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <Button Content="{Binding Path=Value}"
            Command="{Binding Path=IncrementValueCommand}" />

</UserControl>

后面的代码:

Public Class UserControl1

    Public Shared ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Integer), GetType(UserControl1), New PropertyMetadata(1))

    Public Property IncrementValueCommand As ICommand

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        IncrementValueCommand = New RelayCommand(AddressOf IncrementValue)

    End Sub

    Public Property Value() As Integer
        Get
            Return GetValue(ValueProperty)
        End Get
        Set(value As Integer)
            SetValue(ValueProperty, value)
        End Set
    End Property

    Private Sub IncrementValue()
        Value += 1
    End Sub

End Class

第二种方法:INotifyPropertyChanged for Value

XAML:

<UserControl x:Class="UserControl2"
             x:Name="root"
             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:WpfApp1"
             DataContext="{Binding RelativeSource={RelativeSource Self}}"
             mc:Ignorable="d"
             d:DesignHeight="100"
             d:DesignWidth="200"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <Button Content="{Binding Path=Value}"
            Command="{Binding Path=IncrementValueCommand}" />

</UserControl>

后面的代码:

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Class UserControl2
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Private _value As Integer = 1
    Public Property IncrementValueCommand As ICommand

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        IncrementValueCommand = New RelayCommand(AddressOf IncrementValue)

    End Sub

    Public Property Value() As Integer
        Get
            Return _value
        End Get
        Set(value As Integer)
            If _value <> value Then
                _value = value
                NotifyPropertyChanged()
            End If
        End Set
    End Property

    ' This method is called by the Set accessor of each property.  
    ' The CallerMemberName attribute that is applied to the optional propertyName  
    ' parameter causes the property name of the caller to be substituted as an argument.  
    Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

    Private Sub IncrementValue()
        Value += 1
    End Sub

End Class

我省略了RelayCommand类,它是ICommand的标准实现。

任何帮助将不胜感激。


工作代码(感谢Peter Duniho的回答)

首先创建IncrementValueCommand,以调整代码隐藏的构造函数:

Public Sub New()

    ' Add any initialization after the InitializeComponent() call? Nah
    IncrementValueCommand = New RelayCommand(AddressOf IncrementValue)

    ' This call is required by the designer.
    InitializeComponent()

End Sub

1 个答案:

答案 0 :(得分:1)

正如我所解释的in this comment,在尝试使用命令更新值的这种特定变体中,问题在于您正在初始化IncrementValueCommand属性 在类构造函数中对InitializeComponent()的调用。

InitializeComponent()调用中设置了对该属性的绑定,即在XAML中的Command="{Binding Path=IncrementValueCommand}"。进行该调用时,该属性的默认值仍为null

稍后再为该属性分配值时,由于该属性是自动实现的属性,因此该赋值不会导致发生属性更改通知,因此绑定永远不会更新以反映新值。

您可以为该属性实现属性更改通知,就像对Value属性所做的那样,也可以(如我之前所建议的那样)在构造函数内移动分配,以使其发生< em>之前调用InitializeComponent,而不是之后。