将我的模型中的对象绑定到WPF用户控件应该如何操作?

huangapple go评论58阅读模式
英文:

How do I bind to an object in my model to a user control in WPF?

问题

I'm trying to populate labels in a user control. The code-behind my user control creates an object, and I'm trying to bind the label contents to properties in that object. The class creating the object implements INotifyPropertyChanges, and has several public properties. I created binding within the XAML, and Visual Studio has picked this up, with intellisense offering me the properties to bind to. However, when I run, the labels are all blank.
If I create a property directly in my code behind which just calls from the object (and appropriately change my datacontext), it works.

I'm not too experienced with WPF - I must have missed something but I just don't know what?!

When my XAML looks like this, neither label is populated. If I adjust the data context to the control rather than the instrument object, The ConStatus label appropriately populates (but does not update as the user control doesn't implement INotifyPropertyChange):

<WrapPanel Grid.Row="1" DataContext="{Binding instrument}">
    <Label Name="PortName" Width="100" Content="{Binding ConnectionString}" HorizontalAlignment="Right"/>
    <Label  Name="ConStatus" Width="200" Content="{Binding UniName}" HorizontalAlignment="Left"/>
</WrapPanel>

My code-behind looks like this:

Public Class UnifaceControl
    Inherits UserControl

    Public instrument As UnifaceModel

    Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        FindUniface("uniface")
    End Sub

    Public Sub FindUniface(Portname As String)
        instrument = New UnifaceModel(Portname)
        instrument.Connect()
    End Sub

    ReadOnly Property UniName
        Get
            Return instrument.Connected
        End Get
    End Property
End Class

And here's a sample of the UnifaceModel object:

Public Class UnifaceModel
    Implements INotifyPropertyChanged

    Shared Log As NLog.Logger = NLog.LogManager.GetCurrentClassLogger()

    Dim _ConnectionString As String
    Public Property ConnectionString As String
        Get
            Return _ConnectionString
        End Get
        Set(value As String)
            _ConnectionString = value
            OnPropertyChanged()
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
End Class
英文:

I'm trying to populate labels in a user control. The code-behind my user control creates an object, and I'm trying to bind the label contents to properties in that object. The class creating the object implements INotifyPropertyChanges, and has several public properties. I created binding within the XAML, and Visual Studio has picked this up, with intellisense offering me the properties to bind to. However, when I run, the labels are all blank.
If I create a property directly in my code behind which just calls from the object (and appropriately change my datacontext), it works.

I'm not too experienced with WPF - I must have missed something but I just don't know what?!

When my XAML looks like this, neither label is populated. If I adjust the data context to the control rather than the instrument object, The ConStatus label appropriately populates (but does not update as the user control doesn't implement INotifyPropertyChange:

        &lt;WrapPanel Grid.Row=&quot;1&quot; DataContext=&quot;{Binding instrument}&quot;&gt;
            &lt;Label Name=&quot;PortName&quot; Width=&quot;100&quot; Content=&quot;{Binding ConnectionString}&quot;  HorizontalAlignment=&quot;Right&quot;/&gt;
            &lt;Label  Name=&quot;ConStatus&quot; Width=&quot;200&quot; Content=&quot;{Binding UniName}&quot; HorizontalAlignment=&quot;Left&quot;/&gt;
        &lt;/WrapPanel&gt;

My code-behind looks like this:

Public Class UnifaceControl
    Inherits UserControl

    Public instrument As UnifaceModel

    Sub New()
        &#39; This call is required by the designer.
        InitializeComponent()
        &#39; Add any initialization after the InitializeComponent() call.
        FindUniface(&quot;uniface&quot;)
    End Sub

    Public Sub FindUniface(Portname As String)
        instrument = New UnifaceModel(Portname)
        instrument.Connect()
    End Sub

    ReadOnly Property UniName
        Get
            Return instrument.Connected
        End Get
    End Property

End Class

And here's a sample of the UnifaceModel object:

Public Class UnifaceModel
    Implements INotifyPropertyChanged

    Shared Log As NLog.Logger = NLog.LogManager.GetCurrentClassLogger()

    Dim _ConnectionString As String
    Public Property ConnectionString As String
        Get
            Return _ConnectionString
        End Get
        Set(value As String)
            _ConnectionString = value
            OnPropertyChanged()
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub OnPropertyChanged(&lt;CallerMemberName&gt; Optional propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

答案1

得分: 0

instrument 必须是一个属性,以便您可以绑定到它:

Public Property instrument As UnifaceModel

但您还需要在控件或其父窗口的某个地方设置DataContext

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

    ' Set the DataContext to itself
    DataContext = Me

    ' Add any initialization after the InitializeComponent() call.
    FindUniface("uniface")
End Sub

由于您当前绑定到UserControl本身和instrument的属性,所以不应将DataContext绑定到instrument

<WrapPanel Grid.Row="1">
    <Label Name="PortName" Width="100" Content="{Binding instrument.ConnectionString}"  HorizontalAlignment="Right"/>
    <Label Name="ConStatus" Width="200" Content="{Binding UniName}" HorizontalAlignment="Left"/>
</WrapPanel>
英文:

instrument must be a property for you to be able to bind to it:

Public Property instrument As UnifaceModel

But you also need to set the DataContext of the control or its parent window somewhere:

Sub New()
    &#39; This call is required by the designer.
    InitializeComponent()

    &#39; Set the DataContext to itself
    DataContext = Me

    &#39; Add any initialization after the InitializeComponent() call.
    FindUniface(&quot;uniface&quot;)
End Sub

Since you currently bind to properties of both UserControl itself and instrument, you should not bind the DataContext to instrument:

&lt;WrapPanel Grid.Row=&quot;1&quot;&gt;
    &lt;Label Name=&quot;PortName&quot; Width=&quot;100&quot; Content=&quot;{Binding instrument.ConnectionString}&quot;  HorizontalAlignment=&quot;Right&quot;/&gt;
    &lt;Label  Name=&quot;ConStatus&quot; Width=&quot;200&quot; Content=&quot;{Binding UniName}&quot; HorizontalAlignment=&quot;Left&quot;/&gt;
&lt;/WrapPanel&gt;

huangapple
  • 本文由 发表于 2023年5月17日 22:22:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273159.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定