【问题标题】:WPF Trouble Updating a Textbox from a variableWPF问题从变量更新文本框
【发布时间】:2012-06-18 14:56:43
【问题描述】:

使用 WPF 和 VB.net,我想用当前日期和时间更新文本块中的文本框。我使用了一个计时器,它似乎正在触发,并将对象属性设置为“现在”。 我正在使用 iNotifyPropertyChanged。

我得到的只是一个没有数据的空文本框。你能帮我吗?也许我的上下文已经关闭了?

XAML

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
    <TextBlock DataContext="oTime"> 
        <TextBox x:Name="myTextBox" 
                 Width="200" Height="50" Foreground="Black" 
                 Text="{Binding Path=oTime.TimeUpdate}"></TextBox>
    </TextBlock>
</Grid>
</Window>

VB 代码

Imports System.ComponentModel
Imports System.Windows.Threading

Class MainWindow
  Public oTime As TimeUpdate = New TimeUpdate
  Private dpTimer As DispatcherTimer

  Private Sub TextBlock_SourceUpdated(ByVal sender As System.Object, ByVal e As System.Windows.Data.DataTransferEventArgs)

  End Sub

  Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
      dpTimer = New DispatcherTimer
      dpTimer.Interval = TimeSpan.FromMilliseconds(1000)
      AddHandler dpTimer.Tick, AddressOf TickMe
      dpTimer.Start()
  End Sub

  Private Sub TickMe()
      oTime.TimeUpdate = Now.ToString
      Debug.Print(oTime.TimeUpdate)
  End Sub

End Class

Public Class TimeUpdate
Implements INotifyPropertyChanged

  Private sTime As String

  'Declare the Event
  Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

  Public Property TimeUpdate() As String
      Get
          Return sTime

      End Get
      Set(ByVal value As String)
          sTime = value
          'Call onPropertyChanged whenever the property is updated
          OnPropertyChanged("TimeUpdate")
      End Set

  End Property

  Protected Sub OnPropertyChanged(ByVal name As String)
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
  End Sub

End Class

【问题讨论】:

  • 虽然它完全有效,但为什么要将 TextBox 放在 TextBlock 中? Textblock 是一个轻量级的标签,只显示一个简单的文本。只需删除文本块,没有必要。
  • 我不知道为什么。我只是在尝试不同的东西来让它发挥作用。我试图更改文本块中的某些内容,但它不允许我这样做。现在不记得了。就像我说的,我现在才编写 WPF 几天,所以我得到了 OJT。这里有几个人告诉我,我应该只专注于 winforms,但我喜欢 WPF 可以做的事情。它们都不能在 WPF 中工作。
  • WPF 与 Windows 窗体有很大不同。转换可能很困难,但值得。我经常使用winforms,但现在,我不记得如何做winforms :) 我喜欢wpf。 WPF 的一个非常重要的部分是Databinding 我建议你阅读它。
  • 好的,我会尝试阅读它。绑定到数据库连接和类似的东西似乎有很多。但我只是想将文本块或文本框中的数据设置为代码中的值。虽然要在 WPF 文本框中获取变量值,但要跳转很多。
  • 数据绑定与数据库没有直接关系。就像您想将 TextBox.Text 属性绑定到您的 TimeUpdate 一样。但看起来,您需要更好地了解此绑定的工作原理以及 DataContext 是什么。

标签: wpf vb.net binding inotifypropertychanged


【解决方案1】:

似乎缺少一些东西。首先没有设置窗口的DataContext。你可以在构造函数中做到这一点:

Public Sub New()
    DataContext = oTime
End Sub

这允许您的视图查看 TimeUpdate 类的内容。

然后更改您的 XAML(直接绑定到 TimeUpdate 属性):

<Grid> 
    <TextBox x:Name="myTextBox" 
             Width="200" Height="50" Foreground="Black" 
             Text="{Binding Path=TimeUpdate}"></TextBox>
</Grid>

更新: 另一种方法是在 Window 标记中添加 DataContext 行。这样,您的 MainWindow 类对视图可见,您可以绑定到公共属性。

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">

现在创建一个公共属性来访问该对象:

Public Property OTime() As TimeUpdate
    Get
        Return oTime
    End Get
    Set
        oTime = value
    End Set
End Property

并将文本框绑定到它:

<Grid> 
    <TextBox x:Name="myTextBox" 
             Width="200" Height="50" Foreground="Black" 
             Text="{Binding Path=OTime.TimeUpdate}"></TextBox>
</Grid>

【讨论】:

  • 好的,它成功了。这是最好的方法吗?我这么快就感谢你所有的cmets。我想我将不得不浏览这段代码,看看我是否能更好地理解数据上下文。那么这是您必须在 WPF 中执行的操作以在 WPF 表单上显示变量值吗?还是有更简单的方法?
  • 我不确定这是否是最好的方法。它适合你的例子。另一种方法是在您的视图中设置 DataContext 并通过您可以绑定的属性(来自 MainWindow 类)公开不同的对象。我会用例子来扩展答案。
  • 谢谢。今晚我会坐下来,看看我是否可以逐步完成这种绑定方法,看看我是否可以遵循它。这可能是一种更好的方法,因此它允许我访问其他几个对象,而不是每次使用不同的变量时都必须指定绑定。谢谢。
【解决方案2】:

尝试改变这个

OnPropertyChanged("TimeUpdate")

到这里

OnPropertyChanged("oTime")

另外,请确保您已在根网格上设置 DataContext

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=.}">

【讨论】:

  • 如何更改TimeUpdate.TimeUpdate 定义中的OnPropertyChanged 调用以引用MainWindow 中的TimeUpdate 实例的名称可能解决问题?
  • oTime 是您路径的根。由于 TimeUpdate 是 oTime 上的一个属性(它本身不支持 INotifyPropertychanfged),因此您必须在属性路径上进行通知。它有效,相信我:)
  • 我不明白为什么您建议从类定义中引用特定实例的名称。似乎是糟糕的设计。如果该类在其他地方使用不同的实例名称会发生​​什么?通话会失败,是吗?这就是问题的根源 - 通知没有正确发生。
  • 我的回答是在 OP 的问题的背景下,设计没有被辩论。该解决方案适用于 OP 的问题。
  • -1 提高“oTime”是一个坏主意,您正在更改 TimeUpdate,而不是 oTime,实际上就像 EsotericScreenName 所说的那样,在这种情况下甚至不知道“oTime”这个名称。虽然我们确实不是在谈论设计,但给出一个如此偏离的解决方案也无济于事,它会使 OT 走上错误的轨道。有时 hack 很好也很有必要,但应该明确提及。
【解决方案3】:

尝试改变这个:

 Text="{Binding Path=oTime.TimeUpdate}"

到:

 Text="{Binding Path=oTime.TimeUpdate, UpdateSourceTrigger="PropertyChanged"}"

【讨论】:

    【解决方案4】:

    我认为您的数据上下文已关闭。如果我错了,对我来说是正确的,但看起来您将其设置为字符串值而不是对象。 oTime 是您在 XAML 中作为资源创建的对象吗?如果是这样,您将需要使用 StaticResource 来获取它。否则你需要实例化。

    例如。

    <TextBlock >
        <TextBlock.DataContext>
            <!-- This will instantiate the object-->
            <local:TimeUpdate/> 
        </TextBlock.DataContext>
         <TextBox x:Name="myTextBox" Width="200" Height="50" Foreground="Black" Text="{Binding Path=TimeUpdate}"></TextBox>
    </TextBlock>
    

    编辑:我刚刚注意到您在 MainWindow 类中实例化了一个 TimeUpdate 对象。在这种情况下,我会在后面的代码中将 Window 的 DataContext 设置为自身,并使 oTime 成为一个属性。这样您就不必为TextBlock 设置DataContext。它将使用父级的 DataContext,在本例中为 Window。您的 XAML 现在如下所示:

    <TextBlock>
         <TextBox x:Name="myTextBox" Width="200" Height="50" Foreground="Black" Text="{Binding Path=oTime.TimeUpdate}"/>
    </TextBlock>
    

    【讨论】:

    • 谁反对?第一部分是正确的。 DataContext="oTime" 将 Datacontext 设置为一个名为 oTime 的字符串,并且不指向对象。最佳答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多