在属性背后的代码上不会调用绑定

时间:2017-01-27 17:21:04

标签: wpf vb.net xaml

所以我在其中有一个带有一些复选框的网格,并希望将它们全部设置为只读,我在下面添加了IsEnabled部分:

<Grid IsEnabled="{Binding IsFieldReadOny}">

在后面的代码中添加了这个:

Private _isFieldReadOnly As Boolean = True
Public Property IsFieldReadOny() As Boolean
    Get
        Return _isFieldReadOnly
    End Get
    Set(value As Boolean)
        _isFieldReadOnly = value
    End Set
End Property

但是当我放置断点时,它不会被击中或做任何事情。 如果我手动硬编码为网格的True,那么它的工作原理。 我是WPFVB语法的新手,所以我做得不对,这可能很容易。

2 个答案:

答案 0 :(得分:2)

这是一个非常简单的MVVM示例,并通过TONS的一种方式进行绑定。绑定本身有很多选项遍历可视树与“相关源”#39;和范围。以及模式选项和其他设置。我选择专注于保持简单。我只想要一个有文本框的视图,你可以改变自己,你可以点击一个按钮,一个标签将从你改变的文本更新。

所以这是一个基本观点:

<Window x:Class="MainWindow"
        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:local="clr-namespace:SimpleWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
      <TextBox Text="{Binding Text}" Height="30" />
      <Button Content="Example" Command="{Binding DoCommand}" />
    <Label Content="{Binding Output}" Height="30" />
  </StackPanel>
</Window>

我想为&#39; DelegateCommand&#39;设置一个帮助类。您可以通过多种方式执行此操作,但实际上我正在保存重复方法,以便以后重用命令以帮助使用ICommand接口。

Public Class DelegateCommand(Of T)
  Implements ICommand
  Private _execute As Action(Of T)

  Public Sub New(execute As Action(Of T))
    _execute = execute
  End Sub

  Public Event CanExecuteChanged As EventHandler
  Private Event ICommand_CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged

  Private Function ICommand_CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
    Return True
  End Function

  Private Sub ICommand_Execute(parameter As Object) Implements ICommand.Execute
    _execute.Invoke(DirectCast(parameter, T))
  End Sub
End Class

现在我的代码背后的视图应该是非常小的,除了这个:

Class MainWindow
  Public Sub New()

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

    ' Add any initialization after the InitializeComponent() call.
    Me.DataContext = New MainViewModel()
  End Sub

End Class

我的MainViewModel非常简单,在这种情况下非常简单,我只实现了INotifyPropertyChanged。我通常会在基类中完成大部分这样的事情,并在更大的解决方案中继承它。

Imports System.ComponentModel

Public Class MainViewModel
  Implements INotifyPropertyChanged

  Private _text As String
  Public Property Text As String
    Get
      Return _text
    End Get
    Set(ByVal value As String)
      _text = value
      OnPropertyChanged(NameOf(Text))
    End Set
  End Property

  Private _output As String
  Public Property Output As String
    Get
      Return _output
    End Get
    Set(ByVal value As String)
      _output = value
      OnPropertyChanged(NameOf(Output))
    End Set
  End Property

  Public Sub New()
    _text = "Test"
  End Sub

  Public ReadOnly Property DoCommand As New DelegateCommand(Of Object)(AddressOf DoIt)

  Private Sub DoIt(obj As Object)
    Output = $"{Text} {DateTime.Now.ToLongDateString}"
  End Sub

#Region "Implement INotifyProperty Changed"
  Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

  Public Sub OnPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
  End Sub
#End Region
End Class

答案 1 :(得分:1)

当您使用通用绑定时,您正在查看对象的DataContext,而通用我指的是没有任何其他参数的{Binding PropertyName}。为了绑定到代码中的属性(我不建议这样做),您需要告诉绑定查看该位置。您还需要使用依赖项属性来绑定UIElements,因为它已经内置了。

因此,为了完成这项工作,我已经将网格命名为“窗口”窗口中​​的窗口&#39;。然后我给出了绑定表达式与属性的直接连接。

 <Grid IsEnabled="{Binding IsReadOnlyField, ElementName=window}" />

然后我又添加了一个绑定到Checkbox的东西。

 <CheckBox Content="Is Grid Enabled" IsChecked="{Binding IsReadOnlyField, ElementName=window}" />

然后在我后面的代码中,我将属性更改为DependencyProperty。

public bool IsReadOnlyField
    {
        get { return (bool)GetValue(IsReadOnlyFieldProperty); }
        set { SetValue(IsReadOnlyFieldProperty, value); }
    }

    public static readonly DependencyProperty IsReadOnlyFieldProperty =
        DependencyProperty.Register(nameof(IsReadOnlyField), typeof(bool), typeof(MainWindow));

这将使绑定工作。

如果您没有使用后面的代码并且绑定到ViewModel或任何类,您最好将该类接口设置为INotifyPropertyChanged(尽管您也可以使该ViewModel继承自DependencyObject并使用相同的DependencyPropery ...它&#39 ; s通常用于UI元素)。然后正常写入属性,并在setter中调用属性changed事件。但是,您很可能将绑定设置回原来的方式,并将ViewModel作为DataContext。

有很多关于绑定的解释,因为它可以非常灵活并且使用许多不同的方式。一旦你得到它,并且学习更多的绑定方法将很简单。我建议确切地学习如何进行绑定,以便您可以操纵并选择适合任何情况的最佳绑定。