【问题标题】:Binding to a TextBox within a ListView?绑定到 ListView 中的文本框?
【发布时间】:2011-08-14 22:22:26
【问题描述】:

我已经为此寻找答案将近一周了,但我似乎无法找到解决方法。我认为这是一件相对简单的事情......

我有一个 ListView,一个 GridViewColumn 包含 TextBox 项。我想在 ListView 正下方放置一个标签,并用所有 TextBoxes 中的项目总和填充它。每当有人更改任何文本框中的值时,总和也应该更改。

我知道我需要使用转换器来获取总和...但我不知道如何正确绑定...

任何帮助将不胜感激!

编辑:我最终以稍微不同的方式解决了这个问题。我将在下面发布我的解决方案。

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:converters="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <XmlDataProvider x:Key="myParties" XPath="Parties" Source="XMLFile1.xml" />
        <CollectionViewSource x:Key="myCollectionViewSource" Source="{StaticResource myParties}" />
        <converters:SumConverter x:Key="mySumConverter" />
    </Window.Resources>

    <StackPanel>
        <Button x:Name="Breakpoint" Click="bpClick" Content="Breakpoint"/>
        <ListView x:Name="myListView" 
                  HorizontalAlignment="Stretch" 
                  ItemsSource="{Binding Source={StaticResource myCollectionViewSource},XPath='Party',Mode=TwoWay}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="100" DisplayMemberBinding="{Binding XPath='@Contact'}" Header="Contact"/>
                    <GridViewColumn DisplayMemberBinding="{Binding XPath='@Qty'}" Header="Q"/>
                    <GridViewColumn DisplayMemberBinding="{Binding XPath='@Amount'}" Header="Amt"/>
                    <GridViewColumn x:Name="tbTot" Header="Tot">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <DockPanel>
                                    <TextBox Width="100" Text="{Binding XPath='@Tot'}" />
                                </DockPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>    
        </ListView>

        <Label Height="22">
            <Label.Content>
                <MultiBinding Converter="{StaticResource mySumConverter}">
                    <Binding ElementName="myListView" Path="Items"/>
                    <Binding ElementName="myListView" Path="Items.Count"/>
                </MultiBinding>
            </Label.Content>
        </Label>
    </StackPanel>
</Window>

XML 文件:

<?xml version="1.0" encoding="utf-8" ?>
<Parties>
  <Party Contact="Jim Shmekel"
         Qty="1"
         Amount="55.00" 
         Tot="55.00"/>
  <Party Contact="Shmi Skywalker"
         Qty="1"
         Amount="20.00" 
         Tot="20.00"/>
  <Party Contact="Jon Ronson"
         Qty="1"
         Amount="23.00" 
         Tot="23.00"/>
</Parties>

求和转换器:

Imports System.Collections.ObjectModel
Imports System.Reflection

<ValueConversion(GetType(Object()), GetType(String))>
Public Class SumConverter : Implements System.Windows.Data.IMultiValueConverter

    Public Function Convert(ByVal values() As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
        Static lvItems As IList
        Static lvItem As Xml.XmlElement
        Dim nVal As Double

        Convert = 0
        lvItems = values(0)
        If lvItems Is Nothing Then Exit Function

        For Each lvItem In lvItems
            'Debug.Print(lvItem.GetAttribute("Tot"))
            If Double.TryParse(lvItem.GetAttribute("Tot"), nVal) Then
                Convert = Convert + nVal
            End If
        Next

    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetTypes() As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack
        ConvertBack = Nothing
    End Function
End Class

【问题讨论】:

    标签: .net wpf vb.net xaml ivalueconverter


    【解决方案1】:

    简单的解决方案(我确定不是最好的)是绑定一个

    ElementName = myListView, Path = Items
    

    在转换器中遍历项目并使用VisualTreeHelper.GetChild()找出项目的底层TextBlock,然后int.TryParse(textBlock.Text, out currentItemValue);

    【讨论】:

    • 嗨 sllev——非常感谢您的快速回复。我认为这让我接近我需要的地方,但是当我现在运行它时,它只会在程序启动时调用我的转换器(Items.Count = 0),而不是再次调用。有任何想法吗? (在上面添加了我的 SumConverter 代码)。
    • @transistor1:见this。 (关键点是:MultiBinding,其中一个绑定针对 items.count-property 以使其更新)
    • 那么当你添加项目时它不会再次被调用?
    • @H.B. - 谢谢 - 这听起来合乎逻辑。我现在要试试。
    • @sllev -- 是的,它只被调用一次。从我一直在阅读的内容来看,这是因为 Items 对象本身在添加项目时不会改变。 H.B 的多重绑定是有意义的,因为 Count 应该改变......
    【解决方案2】:

    我有点失望,因为我真的希望按照 sllev 建议的方式来解决这个问题。对我来说,这似乎是最合乎逻辑的做法。可能还是有办法的,但我还没想通。

    这就是我最终解决这个问题的方法。基本上我所做的是将“Tot”列添加到我的数据源中(虽然它在我上面的问题中,但在我的初始解决方案中并不存在)。我将我的 TextBox 绑定到该列,然后在 ListView 中的 TextBox 的 LostFocus 事件上刷​​新 ListView。 Refresh() 导致 SumConverter 再次被调用。

    希望这对其他人有所帮助 - 这似乎是一个简单的请求,但我已经浪费了大量时间。

    MainWindow.xaml:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:converters="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
    
        <Window.Resources>
            <XmlDataProvider x:Key="myParties" XPath="Parties" Source="XMLFile1.xml" />
            <CollectionViewSource x:Key="myCollectionViewSource" Source="{StaticResource myParties}" />
            <converters:SumConverter x:Key="mySumConverter" />
        </Window.Resources>
    
        <StackPanel>
            <ListView x:Name="myListView" 
                      HorizontalAlignment="Stretch" 
                      ItemsSource="{Binding Source={StaticResource myCollectionViewSource},XPath='Party',Mode=TwoWay}">
    
                <ListView.View>
                    <GridView>
                        <GridViewColumn Width="100" DisplayMemberBinding="{Binding XPath='@Contact'}" Header="Contact"/>
                        <GridViewColumn DisplayMemberBinding="{Binding XPath='@Qty'}" Header="Q"/>
                        <GridViewColumn DisplayMemberBinding="{Binding XPath='@Amount'}" Header="Amt"/>
                        <GridViewColumn x:Name="tbTot" Header="Tot">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <DockPanel>
                                        <TextBox LostFocus="TextBox_LostFocus" Width="100" Text="{Binding XPath='@Tot'}" />
                                    </DockPanel>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>    
            </ListView>
    
            <Label VerticalAlignment="Stretch">
                <Label.Content>
                    <MultiBinding Converter="{StaticResource mySumConverter}">
                        <Binding ElementName="myListView" Path="Items"/>
                        <Binding ElementName="myListView" Path="Items.Count"/>
                    </MultiBinding>
                </Label.Content>
            </Label>
        </StackPanel>
    </Window>
    

    MainWindow.xaml 上的代码隐藏:

    Class MainWindow 
    
            Public Sub New()
                ' This call is required by the designer.
                InitializeComponent()
            End Sub
    
            Private Sub TextBox_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
                myListView.Items.Refresh()
            End Sub
        End Class
    

    SumConverter.vb:

    <ValueConversion(GetType(Object()), GetType(String))>
    Public Class SumConverter : Implements System.Windows.Data.IMultiValueConverter
    
        Public Function Convert(ByVal values() As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert
            Static lvItems As ItemCollection
            Static lvItem As Xml.XmlElement
            Dim nVal As Double
    
            Convert = 0
            lvItems = values(0)
            If lvItems Is Nothing Then Exit Function
    
    
            For Each lvItem In lvItems
                'Debug.Print(lvItem.GetAttribute("Tot"))
                If Double.TryParse(lvItem.GetAttribute("Tot"), nVal) Then
                    Convert = Convert + nVal
                End If
            Next
    
        End Function
    
        Public Function ConvertBack(ByVal value As Object, ByVal targetTypes() As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack
            ConvertBack = Nothing
        End Function
    End Class
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-20
      • 2017-08-05
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 2021-03-05
      相关资源
      最近更新 更多