绑定到 ListView 中的文本框?

发布于 2024-11-29 10:23:55 字数 4369 浏览 6 评论 0原文

我已经寻找这个问题的答案近一周了,但我似乎找不到办法做到这一点。我认为这是一件相对简单的事情...

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

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

任何帮助将不胜感激!

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

<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>

SumConverter:

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

I have been searching for an answer for this for almost a week now, and I can't seem to find a way to do this. I would think it is a relatively simple thing...

I have a ListView, and one GridViewColumn contains TextBox items. I want to put a Label right underneath the ListView, and fill it with the sum of the items in all the TextBoxes. Whenever someone changes a value in any of the TextBoxes, the sum should change, too.

I know I need to use a Converter to get the sum... but I don't know how to get the binding right...

Any help would be greatly appreciated!

EDIT: I ended up solving this in a slightly different way. I will post my solution below.

<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 file:

<?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>

SumConverter:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小ぇ时光︴ 2024-12-06 10:23:55

直接的解决方案(我确信不是最好的)是绑定

ElementName = myListView, Path = Items

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

Straightforward solution (I'm sure not the best) is to bind a

ElementName = myListView, Path = Items

And in converter traverse items and using VisualTreeHelper.GetChild() find out underlying TextBlock of an item and then int.TryParse(textBlock.Text, out currentItemValue);

多像笑话 2024-12-06 10:23:55

我有点失望,因为我真的希望按照 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

I'm a bit disappointed, because I really was hoping to approach this the way the sllev had suggested. To me, that seemed like the most logical way of doing it. There may still be a way, but I haven't figured it out.

Here is how I ended up solving this problem. Basically what I did was add the "Tot" column to my DataSource (it was not there in my initial solution although it is in my question above). I bound my TextBox to that column, and then refreshed the ListView on the LostFocus event of the TextBox within the ListView. The Refresh() causes the SumConverter to be called again.

Hopefully this helps someone else out - it seemed like a simple request but I have wasted a ton of time on it.

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>

CodeBehind on 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文