对 XAML ListView 控件中的 class 属性求和
Summing class attributes in XAML ListView control
我是 C# 的新手,所以我已经为此苦苦挣扎了很长时间,我不知道我应该做什么...
我想对我的 class (sum
+ interestRate_1
) 中的 2 个(或更多)值求和,并在我各自的 ListView
中显示结果我在 ObservableCollections
列表中创建的每个 class 实例的列。
ListView
本身受 ItemSource
约束并包含所有已创建的 Cust
-我试图对其执行计算的对象。
我是 XAML 的新手,所以我不知道它是如何工作的。人们告诉我使用转换器,但我不确定它意味着什么...
这是我试过的:
XAML声明:
<Window x:Class="MyProject.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
Title="MyProject (beta)" Height="450" Width="1000" MinWidth="1000" MinHeight="450" ResizeMode="CanResize">
XAML ListView
:
<ListView x:Name="ListTest" Margin="10,150,10,66" Background="#FF0077B6" Foreground="White" MouseDoubleClick="ListTest_MouseDoubleClick" SelectionChanged="ListTest_SelectionChanged" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding CustList}" Grid.RowSpan="2">
<ListView.Effect>
<DropShadowEffect/>
</ListView.Effect>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="136" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Amount (€)" Width="80" DisplayMemberBinding="{Binding Sum}"/>
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
C# 转换器 + Cust
对象列表:
namespace MyProject
{
public class AddConverter : IMultiValueConverter
{
public object Convert(object[] values, Type tagetType, object parameter, CultureInfo culture)
{
var decimalValues = values.Cast<decimal>().ToArray();
var resultSum = decimalValues.Sum().ToString();
return resultSum;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public partial class MainWindow : Window
{
public ObservableCollection<Cust> CustList = new ObservableCollection<Cust>();
public MainWindow()
{
InitializeComponent();
ListTest.ItemsSource = CustList;
}
//...
相关 Class 属性/属性:
public class Cust
{
public Name {get; set;}
private decimal sum;
public decimal Sum
{
get { return sum; }
set { sum = value; }
}
public decimal interestRate_1 { get; set; } = 3.0M;
public decimal interestRate_2 { get; set; } = 5.0M;
// ...
我知道 XAML 无法从 .cs 文件中找到转换器,并且我在我尝试转换的列中使用了两次 Header
(我不明白)。我完全迷失在这里了吗?
欢迎来到 xaml 和 c# 的土地:)
WPF 或 XAML 和 C# 的关键概念是 MVVM,它代表模型视图视图模型
在您的示例中,Cust class 将是模型
XAML 后面的代码就是视图。
缺少的是 ViewModel。这是您的代码和视图之间的连接。
这是我印象深刻的观点
- 你应该看看 MVVM 和绑定的概念:
- 顾客就是模特
- 转换器通常用于绑定一个值,例如
- if(值 == null) return Visibility.Collapsed
所以我认为它不是这里工作的正确工具。
- 您可以考虑在 listView 中使用 DataGrid 控件而不是 GridView
- 如果您想使用 ListView,则必须搜索模板(尤其是 ItemTemplates)
- 如果您想更改您的值并更新您的视图,您必须查找 INotifyPropertyChanged 或找到一个基本实现来设置您的属性。
但无论如何这里有一个解决你的问题的方法:
<Window x:Class="WpfApp1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<DataGrid ItemsSource="{Binding Custs}"/>
<Label Content="Result"/>
<Label Content="{Binding ResultSum}"/>
</StackPanel>
</Window>
下面是一个视图模型的基本示例
public class MainWindowViewModel
{
public ObservableCollection<Cust> Custs { get; set; }
public decimal ResultSum { get; set; }
public MainWindowViewModel()
{
Custs = new ObservableCollection<Cust>
{
new Cust
{
Name = "Joe",
Sum = 1.2M,
},
new Cust
{
Name = "Jane",
Sum = 3.2M,
},
};
ResultSum = Custs.Sum(cust => cust.Sum);
}
}
以及如何使用它
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
还有你的客户class
public class Cust
{
public string Name
{
get;
set;
}
private decimal sum;
public decimal Sum
{
get { return sum; }
set { sum = value; }
}
public decimal interestRate_1 { get; set; } = 3.0M;
public decimal interestRate_2 { get; set; } = 5.0M;
}
The result looks like this
找不到转换器,因为没有它的实例。在 XAML 中的任何资源字典中创建一个实例,例如应用程序资源或本地 ListView.Resources
.
<ListView.Resources>
<local:AddConverter x:Key="AddConverter"/>
</ListView.Resources>
ItemsSource
的绑定是多余的,因为您已经在代码中分配它,使用或其他。
ItemsSource="{Binding CustList}"
ListTest.ItemsSource = CustList;
但是,ItemSource
绑定只有在正确设置数据上下文的情况下才会起作用,例如:
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
或者像这样在 XAML 标记中。
<Window x:Class="MyProject.MainWindow"
...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
最后,它说你分配了两次header,因为GridViewColumn
的直接内容也分配了Header
属性。明确地使用 DisplayMemberBinding
属性。
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
这是您 ListView
的完整代码。
<ListView x:Name="ListTest" Margin="10,150,10,66" Background="#FF0077B6" Foreground="White" MouseDoubleClick="ListTest_MouseDoubleClick" SelectionChanged="ListTest_SelectionChanged" IsSynchronizedWithCurrentItem="True" Grid.RowSpan="2">
<ListView.Resources>
<local:AddConverter x:Key="AddConverter"/>
</ListView.Resources>
<ListView.Effect>
<DropShadowEffect/>
</ListView.Effect>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="136" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Amount (€)" Width="80" DisplayMemberBinding="{Binding Sum}"/>
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
您不一定需要值转换器。您还可以在 Cust
中公开计算的 属性 并改为绑定它。这取决于您的要求。
public class Cust
{
// ...your other code.
public decimal AmountWithInterest => sum + interestRate_1;
}
<GridViewColumn Header="Amount With Interest (€)" Width="80" DisplayMemberBinding="{Binding AmountWithInterest}"/>
另请注意,您没有 implement INotifyPropertyChanged
,这意味着对您的属性所做的更改和计算的 属性 不会反映在用户界面中。
除了你得到的错误,你应该熟悉 MVVM pattern。
我是 C# 的新手,所以我已经为此苦苦挣扎了很长时间,我不知道我应该做什么...
我想对我的 class (sum
+ interestRate_1
) 中的 2 个(或更多)值求和,并在我各自的 ListView
中显示结果我在 ObservableCollections
列表中创建的每个 class 实例的列。
ListView
本身受 ItemSource
约束并包含所有已创建的 Cust
-我试图对其执行计算的对象。
我是 XAML 的新手,所以我不知道它是如何工作的。人们告诉我使用转换器,但我不确定它意味着什么...
这是我试过的:
XAML声明:
<Window x:Class="MyProject.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
Title="MyProject (beta)" Height="450" Width="1000" MinWidth="1000" MinHeight="450" ResizeMode="CanResize">
XAML ListView
:
<ListView x:Name="ListTest" Margin="10,150,10,66" Background="#FF0077B6" Foreground="White" MouseDoubleClick="ListTest_MouseDoubleClick" SelectionChanged="ListTest_SelectionChanged" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding CustList}" Grid.RowSpan="2">
<ListView.Effect>
<DropShadowEffect/>
</ListView.Effect>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="136" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Amount (€)" Width="80" DisplayMemberBinding="{Binding Sum}"/>
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
C# 转换器 + Cust
对象列表:
namespace MyProject
{
public class AddConverter : IMultiValueConverter
{
public object Convert(object[] values, Type tagetType, object parameter, CultureInfo culture)
{
var decimalValues = values.Cast<decimal>().ToArray();
var resultSum = decimalValues.Sum().ToString();
return resultSum;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public partial class MainWindow : Window
{
public ObservableCollection<Cust> CustList = new ObservableCollection<Cust>();
public MainWindow()
{
InitializeComponent();
ListTest.ItemsSource = CustList;
}
//...
相关 Class 属性/属性:
public class Cust
{
public Name {get; set;}
private decimal sum;
public decimal Sum
{
get { return sum; }
set { sum = value; }
}
public decimal interestRate_1 { get; set; } = 3.0M;
public decimal interestRate_2 { get; set; } = 5.0M;
// ...
我知道 XAML 无法从 .cs 文件中找到转换器,并且我在我尝试转换的列中使用了两次 Header
(我不明白)。我完全迷失在这里了吗?
欢迎来到 xaml 和 c# 的土地:)
WPF 或 XAML 和 C# 的关键概念是 MVVM,它代表模型视图视图模型 在您的示例中,Cust class 将是模型 XAML 后面的代码就是视图。 缺少的是 ViewModel。这是您的代码和视图之间的连接。
这是我印象深刻的观点
- 你应该看看 MVVM 和绑定的概念:
- 顾客就是模特
- 转换器通常用于绑定一个值,例如
- if(值 == null) return Visibility.Collapsed 所以我认为它不是这里工作的正确工具。
- 您可以考虑在 listView 中使用 DataGrid 控件而不是 GridView
- 如果您想使用 ListView,则必须搜索模板(尤其是 ItemTemplates)
- 如果您想更改您的值并更新您的视图,您必须查找 INotifyPropertyChanged 或找到一个基本实现来设置您的属性。
但无论如何这里有一个解决你的问题的方法:
<Window x:Class="WpfApp1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<DataGrid ItemsSource="{Binding Custs}"/>
<Label Content="Result"/>
<Label Content="{Binding ResultSum}"/>
</StackPanel>
</Window>
下面是一个视图模型的基本示例
public class MainWindowViewModel
{
public ObservableCollection<Cust> Custs { get; set; }
public decimal ResultSum { get; set; }
public MainWindowViewModel()
{
Custs = new ObservableCollection<Cust>
{
new Cust
{
Name = "Joe",
Sum = 1.2M,
},
new Cust
{
Name = "Jane",
Sum = 3.2M,
},
};
ResultSum = Custs.Sum(cust => cust.Sum);
}
}
以及如何使用它
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
还有你的客户class
public class Cust
{
public string Name
{
get;
set;
}
private decimal sum;
public decimal Sum
{
get { return sum; }
set { sum = value; }
}
public decimal interestRate_1 { get; set; } = 3.0M;
public decimal interestRate_2 { get; set; } = 5.0M;
}
The result looks like this
找不到转换器,因为没有它的实例。在 XAML 中的任何资源字典中创建一个实例,例如应用程序资源或本地 ListView.Resources
.
<ListView.Resources>
<local:AddConverter x:Key="AddConverter"/>
</ListView.Resources>
ItemsSource
的绑定是多余的,因为您已经在代码中分配它,使用或其他。
ItemsSource="{Binding CustList}"
ListTest.ItemsSource = CustList;
但是,ItemSource
绑定只有在正确设置数据上下文的情况下才会起作用,例如:
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
或者像这样在 XAML 标记中。
<Window x:Class="MyProject.MainWindow"
...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
最后,它说你分配了两次header,因为GridViewColumn
的直接内容也分配了Header
属性。明确地使用 DisplayMemberBinding
属性。
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
这是您 ListView
的完整代码。
<ListView x:Name="ListTest" Margin="10,150,10,66" Background="#FF0077B6" Foreground="White" MouseDoubleClick="ListTest_MouseDoubleClick" SelectionChanged="ListTest_SelectionChanged" IsSynchronizedWithCurrentItem="True" Grid.RowSpan="2">
<ListView.Resources>
<local:AddConverter x:Key="AddConverter"/>
</ListView.Resources>
<ListView.Effect>
<DropShadowEffect/>
</ListView.Effect>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="136" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Amount (€)" Width="80" DisplayMemberBinding="{Binding Sum}"/>
<GridViewColumn Header="Amount With Interest (€)" Width="80">
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource AddConverter}">
<Binding Path="Sum"/>
<Binding Path="interestRate_1"/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
您不一定需要值转换器。您还可以在 Cust
中公开计算的 属性 并改为绑定它。这取决于您的要求。
public class Cust
{
// ...your other code.
public decimal AmountWithInterest => sum + interestRate_1;
}
<GridViewColumn Header="Amount With Interest (€)" Width="80" DisplayMemberBinding="{Binding AmountWithInterest}"/>
另请注意,您没有 implement INotifyPropertyChanged
,这意味着对您的属性所做的更改和计算的 属性 不会反映在用户界面中。
除了你得到的错误,你应该熟悉 MVVM pattern。