【问题标题】:Label with static text and binding带有静态文本和绑定的标签
【发布时间】:2016-04-09 20:23:45
【问题描述】:

我正在尝试获取一个标签来显示特定文本,同时还绑定到 VB.Net 代码中的一个变量。我可以进行绑定,但无法添加静态文本。

到目前为止我所拥有的:

<Label x:Name="TestLabel" Content="{Binding Path=Row, StringFormat='Row #{0}'}" 
                          HorizontalAlignment="Left" 
                          Height="35" 
                          Margin="203,21,0,0" 
                          VerticalAlignment="Top" 
                          Width="83" 
                          FontSize="18">

Public Class Row
    Implements INotifyPropertyChanged

    Private _Row As Byte
    Public Property Row() As Byte
        Get
            Return _Row
        End Get
        Set(ByVal value As Byte)
            _Row = value

            OnPropertyChanged(New PropertyChangedEventArgs("Row"))
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
        If Not PropertyChangedEvent Is Nothing Then
            RaiseEvent PropertyChanged(Me, e)
        End If
    End Sub
End Class

Private Rows As New Row

Public Sub New()
    InitializeComponent()
    TestLabel.DataContext = Rows
    Rows.Row = MyTextBox.Text.HandledStringtoSByte
End Sub

扩展代码(因为我有自定义扩展):

''' <summary>
''' Handles conversion of string variable to Tiny Integer
''' </summary>
''' <param name="s"></param>
''' <param name="I">Returned if conversion fails.</param>
''' <returns>Signed 8bit Integer</returns>
''' <remarks></remarks>
<Runtime.CompilerServices.Extension()> _
Public Function HandledStringtoSByte(ByRef S As String, Optional I As SByte = 0) As SByte
    Try
        If S = String.Empty Then
            Return I
        Else
            Return SByte.Parse(S)
        End If
    Catch
        Dim result As String = String.Empty
        Dim ReturnByte As SByte
        Dim Parsed As Byte
        For Each Character In S.ToCharArray
            If Character = "-" Then
                If S.Substring(0, 1).ToString <> "-" Then
                    Exit For
                End If
            End If
            If Character = "." Then
                Exit For
            End If
            If Byte.TryParse(Character, Parsed) Then
                result = result + Parsed.ToString
            End If
        Next
        If result <> String.Empty Then
            If SByte.TryParse(result, ReturnByte) Then
                Return SByte.Parse(ReturnByte)
            Else
                If Short.Parse(result) > Short.Parse(SByte.MaxValue.ToString) Then
                    Return SByte.MaxValue
                ElseIf Short.Parse(result) < Short.Parse(SByte.MinValue.ToString) Then
                    Return SByte.MinValue
                Else
                    Return SByte.Parse(ReturnByte)
                End If
            End If
        Else
            Return I
        End If
    End Try
End Function

现在我认为在绑定中使用 stringformat 会添加静态文本并将绑定变量放入 {0} 位置,但给我的只是标签中的绑定变量。

我做错了什么?

【问题讨论】:

  • 顺便说一句,这适用于 TextBlocks。我不认为标签内容与 TextBlock 文本不同。

标签: wpf vb.net xaml data-binding


【解决方案1】:

绑定目标是Content属性,这是Object类型,这就是为什么你不能使用StringFormat绑定。

改为使用ContentStringFormat 属性

<Label Content="{Binding Path=Row}"  
       ContentStringFormat="Row #{0}" />

另一种方法:在 ViewModel 中创建只读属性,以所需格式表示值

Private _Row As Byte
Public Property Row() As Byte
    Get
        Return _Row
    End Get
    Set(ByVal value As Byte)
        _Row = value
        OnPropertyChanged(New PropertyChangedEventArgs("Row"))
        OnPropertyChanged(New PropertyChangedEventArgs("RowText"))
    End Set
End Property

Public ReadOnly Property RowText As String
    Get
        Return String.Format("Row #{0}", Me.Row)
    End Get
End Property

然后将此属性绑定到视图

<Label Content="{Binding Path=RowText}"/>

【讨论】:

  • 当尝试使用只读属性方法时,它不能按我的方式工作,它显示 $ 作为无效字符,没有它只会在标签中显示“Row #{Me”
  • @ARidder101, Dim text As String = $"Some value {variable}" 是 VB.NET 14 的新特性,与 String.Format("Some value {0}", variable) 相同。我用旧语法更新了答案
  • 那行得通,我猜我没有最新的 VB.NET 编译器信息。如果我有时间,我将不得不考虑更新我的软件。
【解决方案2】:

问题在于Binding.StringFormat 是“一个字符串,如果它将绑定值显示为字符串,则指定如何格式化绑定”。在实践中,它似乎仅在目标属性为 string 类型时才有效 - 正如您所指出的,它适用于 TextBlock.Text(类型为 string)而不适用于 Label.Content(类型为 @987654326 @)。有几种方法可以解决这个问题,其中之一是将TextBlock 嵌套在Content 属性中:

<Label>
    <TextBlock Text="{Binding Path=Row, StringFormat='Row #{0}'}" />
</Label>

这并没有真正给可视化树带来任何额外的复杂性,因为字符串默认由TextBlocks 呈现。

否则您可以创建自己的转换器,或者您可以使用 Fabio 的解决方案并利用 Label.ContentStringFormat 属性。

【讨论】:

  • 我不喜欢这个答案,但 Fabio 的解决方案更符合我的要求。感谢您的回复,但不知道为什么我没有想到这一点。
【解决方案3】:

这是一种绑定多个属性的方法:

  • MultiBinding
  • IMultiValueConverter

代码:

Imports System.Globalization
Imports System.Text

Class MainWindow
    Public Shared ReadOnly Text1Property As DependencyProperty = DependencyProperty.Register(
        "Text1", GetType(String), GetType(MainWindow), New PropertyMetadata(Nothing))

    Public Property Text1 As String
        Get
            Return DirectCast(GetValue(Text1Property), String)
        End Get
        Set
            SetValue(Text1Property, Value)
        End Set
    End Property

    Public Shared ReadOnly Text2Property As DependencyProperty = DependencyProperty.Register(
        "Text2", GetType(String), GetType(MainWindow), New PropertyMetadata(Nothing))

    Public Property Text2 As String
        Get
            Return DirectCast(GetValue(Text2Property), String)
        End Get
        Set
            SetValue(Text2Property, Value)
        End Set
    End Property

    Private Sub MainWindow_OnLoaded(sender As Object, e As RoutedEventArgs)
        Me.Text1 = "text1"
        Me.Text2 = "text2"
    End Sub
End Class

转换器:

Class MyConverter
    Implements IMultiValueConverter

    Public Function Convert(values As Object(), targetType As Type, parameter As Object, culture As CultureInfo) _
        As Object Implements IMultiValueConverter.Convert

        If values Is Nothing Then
            Return DependencyProperty.UnsetValue
        End If

        Dim sb As New StringBuilder

        If values.Length > 0 Then
            sb.AppendLine(values(0))
        End If

        If values.Length > 1 Then
            sb.AppendLine(values(1))
        End If

        Return sb.ToString()
    End Function

    Public Function ConvertBack(value As Object, targetTypes As Type(), parameter As Object, culture As CultureInfo) _
        As Object() Implements IMultiValueConverter.ConvertBack
        Throw New NotImplementedException
    End Function
End Class

Xaml:

<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:local="clr-namespace:WpfApplication2"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        x:Name="Window"
        Title="MainWindow"
        Width="525"
        Height="350"
        Loaded="MainWindow_OnLoaded"
        mc:Ignorable="d">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding ElementName=Window, Path=Text1, UpdateSourceTrigger=PropertyChanged}" />
            <TextBox Text="{Binding ElementName=Window, Path=Text2, UpdateSourceTrigger=PropertyChanged}" />
            <Label>
                <Label.Resources>
                    <local:MyConverter x:Key="MyConverter" />
                </Label.Resources>
                <Label.Content>
                    <MultiBinding Converter="{StaticResource MyConverter}">
                        <Binding ElementName="Window" Path="Text1" />
                        <Binding ElementName="Window" Path="Text2" />
                    </MultiBinding>
                </Label.Content>

            </Label>
        </StackPanel>
    </Grid>
</Window>

【讨论】:

  • 很高兴知道如何做到这一点,但这并不是我想要做的。不过谢谢
猜你喜欢
  • 2018-12-20
  • 1970-01-01
  • 1970-01-01
  • 2016-08-20
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
相关资源
最近更新 更多