SelectedItemChanged C# 的问题
Trouble with SelectedItemChanged C#
我在尝试让标签更改为列表框中当前选定的项目时遇到问题。有没有办法在不创建列表的情况下做到这一点?原始选定项目加载得很好,但当值更改或选定项目更改时,我无法更新标签。我需要新鲜的眼睛。
public frmStudentScores()
{
InitializeComponent();
}
//load list box with initial students and grades
private void frmStudentScores_Load(object sender, EventArgs e)
{
lstStudentInfo.Items.Add("Joel Murach|97|91|83");
lstStudentInfo.Items.Add("Doug Lowe|99|93|97");
lstStudentInfo.Items.Add("Anne Boehm|100|100|100");
//set focus on first item in list
lstStudentInfo.SelectedIndex = 0;
//string to seperate items in list box by | to use for labels
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
for (int i = 1; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
//total of all scores in selected row
lblTotal.Text = total.ToString();
//count of the scores in the selected row
lblCount.Text = (str.Length - 1).ToString();
//total divided by the count of the scores in selected row
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
//if the index is changed in the list box
string current = lstStudentInfo.SelectedItem.ToString();
if (lstStudentInfo.SelectedIndex >= 0)
{
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
{
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
{
lblTotal.Text = lstStudentInfo.SelectedItem.ToString();
lblCount.Text = (str.Length - 1).ToString();
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
}
}
}
对你的代码有点困惑。
那里有很多额外的'{''}'。
此外,注释与代码不一致,请参阅下面的注释。
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
//if the index is changed in the list box
string current = lstStudentInfo.SelectedItem.ToString();
#region IF STATEMENT
//Do you want it to only update if changed?
//If so, you need to keep track of the index
if (lstStudentInfo.SelectedIndex >= 0)
{
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
#region UNKNOWN REGION
{
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
#region UNKNOWN REGION
{
lblTotal.Text = lstStudentInfo.SelectedItem.ToString();
lblCount.Text = (str.Length - 1).ToString();
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
#endregion
}
}
#endregion
#endregion
}
我稍微清理了一下,添加了一些错误处理和调试。
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
string current = string.empty;
string lblCount = string.empty;
string lblAverage = string.empty;
string[] str = null;
int total = 0;
int valCount = 0;
int valAvg = 0;
//added some error handling
try{
if (lstStudentInfo.SelectedIndex >= 0)
{
//moved inside if statement, avoid errors if nothing is selected;
current = lstStudentInfo.SelectedItem.ToString();
str = current.Split('|');
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
valCount = (str.Length - 1);
lblCount = valCount.ToString();
valAvg = total/valCount;
lblAverage = valAvg.ToString();
}
}
catch(Exception e){
lblCount = "####";
lblTotal = "####";
current = "ERROR";
}
//moved outside if statment, updates labels when nothing is selected
lblTotal.Text = current;
lblCount.Text = lblCount;
lblAverage.Text = lblAverage;
//added debugging output
Debug.WriteLine($"Student Info Selection Changed: Count: {valCount} Avg: {valAvg}");
}
另一件需要考虑的事情是在多次执行相同代码的地方创建单一方法。
即
private func<lstStudentInfo,string[]> get_items = x => x.Split('|');
希望这能让您走上正确的道路。
XAML 中也可能存在问题,希望调试文本对您有所帮助。
让我们再添加一点灵感?
听起来你没有正确地将你的视图模型绑定到 window。
见下文。
Window.xaml
创建您要显示内容的基本布局。
将所有内容绑定到数据模型,事件选中的项目。
让视图模型处理所有,window 看起来很漂亮。
Window.xaml.cs
创建视图模型的实例并将其指定为数据上下文。
从这里,您可以对视图模型做任何您喜欢的事情,window 将被更新。
My_View_Model.cs
这是绑定到 Window.xaml 的所有内容所在的地方。
请注意,设置 Label_Text 后,它会调用 OnPropertyChanged 方法。
实现这个的方法有很多种,但基本上它们都是一样的,你所做的就是用 window 中需要刷新的对象的名称调用 PropertyChanged 事件。
PropertyChanged 事件关闭并通知 window 更新。
如有任何问题,请随时提出。
Window.xaml:
<Window x:Class="WPF_Label_Update.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:WPF_Label_Update"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="The_WPF_Grid">
<Grid.DataContext>
<local:My_View_Model/>
</Grid.DataContext>
<Grid.Resources>
<DataTemplate x:Key="myDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Path=obj_name}" />
</StackPanel>
</DataTemplate>
</Grid.Resources>
<StackPanel Orientation="Horizontal">
<ListBox x:Name="list_choice"
SelectedItem="{Binding My_Selected_Object}"
SelectionMode="Single"
ItemsSource="{Binding My_Objects}"
ItemTemplate="{StaticResource myDataTemplate}">
</ListBox>
<StackPanel Orientation="Vertical">
<Label x:Name="lbl_output_0" Content="{Binding Label_Text_0}"/>
<Label x:Name="lbl_output_1" Content="{Binding Label_Text_1}"/>
<Label x:Name="lbl_output_2" Content="{Binding Label_Text_2}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPF_Label_Update
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
My_View_Model myViewModel;
private void generateData()
{
StringBuilder _text = new StringBuilder() ;
for (int i = 0; i < 10; i++)
{
_text.Clear();
_text.Append($"Number {i}");
for (int ii = 0; ii < i; ii++)
{
_text.Append($"|{ii}");
}
myViewModel.Add_Item(new my_obj(_text.ToString()));
}
}
public MainWindow()
{
InitializeComponent();
myViewModel =
new My_View_Model();
this.The_WPF_Grid.DataContext = myViewModel;
generateData();
}
private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Something Was Selected");
}
}
}
My_View_Model.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace WPF_Label_Update
{
public class My_View_Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Label_Text_0 { get { return lbl0; } set { lbl0 = value; OnPropertyChanged(); } }
private string lbl0 = string.Empty;
public string Label_Text_1 { get { return lbl1; } set { lbl1 = value; OnPropertyChanged(); } }
private string lbl1 = string.Empty;
public string Label_Text_2 { get { return lbl2; } set { lbl2 = value; OnPropertyChanged(); } }
private string lbl2 = string.Empty;
public my_obj My_Selected_Object {
get {
return mySelectedObj;
}
set {
mySelectedObj = value;
on_mySelectedObjChange();
} }
private my_obj mySelectedObj = null;
/// <summary>
/// Update lables when something changes.
/// </summary>
private void on_mySelectedObjChange()
{
switch (mySelectedObj == null)
{
case true:
Label_Text_0 = string.Empty;
Label_Text_1 = string.Empty;
Label_Text_2 = string.Empty;
break;
default:
Label_Text_0 = mySelectedObj.obj_text;
Label_Text_1 = mySelectedObj.obj_name;
Label_Text_2 = mySelectedObj.obj_count.ToString();
break;
}
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public ObservableCollection<my_obj> My_Objects { get { return my_objs; } }
private readonly ObservableCollection<my_obj> my_objs = new ObservableCollection<my_obj>();
public void Add_Item(my_obj new_obj)
{
my_objs.Add(new_obj);
}
public My_View_Model()
{
}
}
public class my_obj
{
public string obj_text { get; set; }
public string obj_name { get { return obj_text.Split('|')[0]; } }
public int obj_count { get { return obj_text.Split('|').Length; } }
public my_obj(string inputText)
{
this.obj_text = inputText.Trim();
}
}
}
我得到它来处理这个 - 谢谢大家
private void lstStudents_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstStudents.SelectedIndex != -1)
{
string student =
(string)studentScores[lstStudents.SelectedIndex];
string[] scores = student.Split('|');
int total = 0;
for (int i = 1; i < scores.Length; i++)
total += Convert.ToInt32(scores[i]);
int count = scores.Length - 1;
int average = 0;
if (total > 0)
average = total / count;
lblScoreTotal.Text = total.ToString();
lblScoreCount.Text = count.ToString();
lblAverage.Text = average.ToString();
}
}
我在尝试让标签更改为列表框中当前选定的项目时遇到问题。有没有办法在不创建列表的情况下做到这一点?原始选定项目加载得很好,但当值更改或选定项目更改时,我无法更新标签。我需要新鲜的眼睛。
public frmStudentScores()
{
InitializeComponent();
}
//load list box with initial students and grades
private void frmStudentScores_Load(object sender, EventArgs e)
{
lstStudentInfo.Items.Add("Joel Murach|97|91|83");
lstStudentInfo.Items.Add("Doug Lowe|99|93|97");
lstStudentInfo.Items.Add("Anne Boehm|100|100|100");
//set focus on first item in list
lstStudentInfo.SelectedIndex = 0;
//string to seperate items in list box by | to use for labels
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
for (int i = 1; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
//total of all scores in selected row
lblTotal.Text = total.ToString();
//count of the scores in the selected row
lblCount.Text = (str.Length - 1).ToString();
//total divided by the count of the scores in selected row
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
//if the index is changed in the list box
string current = lstStudentInfo.SelectedItem.ToString();
if (lstStudentInfo.SelectedIndex >= 0)
{
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
{
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
{
lblTotal.Text = lstStudentInfo.SelectedItem.ToString();
lblCount.Text = (str.Length - 1).ToString();
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
}
}
}
对你的代码有点困惑。
那里有很多额外的'{''}'。
此外,注释与代码不一致,请参阅下面的注释。
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
//if the index is changed in the list box
string current = lstStudentInfo.SelectedItem.ToString();
#region IF STATEMENT
//Do you want it to only update if changed?
//If so, you need to keep track of the index
if (lstStudentInfo.SelectedIndex >= 0)
{
string[] str = lstStudentInfo.SelectedItem.ToString().Split('|');
int total = 0;
#region UNKNOWN REGION
{
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
#region UNKNOWN REGION
{
lblTotal.Text = lstStudentInfo.SelectedItem.ToString();
lblCount.Text = (str.Length - 1).ToString();
lblAverage.Text = (total / (str.Length - 1)).ToString();
}
#endregion
}
}
#endregion
#endregion
}
我稍微清理了一下,添加了一些错误处理和调试。
private void lstStudentInfo_SelectedIndexChanged(object sender, EventArgs e)
{
string current = string.empty;
string lblCount = string.empty;
string lblAverage = string.empty;
string[] str = null;
int total = 0;
int valCount = 0;
int valAvg = 0;
//added some error handling
try{
if (lstStudentInfo.SelectedIndex >= 0)
{
//moved inside if statement, avoid errors if nothing is selected;
current = lstStudentInfo.SelectedItem.ToString();
str = current.Split('|');
for (int i = 0; i < str.Length; i++)
{
total += int.Parse(str[i]);
}
valCount = (str.Length - 1);
lblCount = valCount.ToString();
valAvg = total/valCount;
lblAverage = valAvg.ToString();
}
}
catch(Exception e){
lblCount = "####";
lblTotal = "####";
current = "ERROR";
}
//moved outside if statment, updates labels when nothing is selected
lblTotal.Text = current;
lblCount.Text = lblCount;
lblAverage.Text = lblAverage;
//added debugging output
Debug.WriteLine($"Student Info Selection Changed: Count: {valCount} Avg: {valAvg}");
}
另一件需要考虑的事情是在多次执行相同代码的地方创建单一方法。
即
private func<lstStudentInfo,string[]> get_items = x => x.Split('|');
希望这能让您走上正确的道路。
XAML 中也可能存在问题,希望调试文本对您有所帮助。
让我们再添加一点灵感?
听起来你没有正确地将你的视图模型绑定到 window。
见下文。
Window.xaml
创建您要显示内容的基本布局。
将所有内容绑定到数据模型,事件选中的项目。
让视图模型处理所有,window 看起来很漂亮。
Window.xaml.cs
创建视图模型的实例并将其指定为数据上下文。
从这里,您可以对视图模型做任何您喜欢的事情,window 将被更新。
My_View_Model.cs
这是绑定到 Window.xaml 的所有内容所在的地方。
请注意,设置 Label_Text 后,它会调用 OnPropertyChanged 方法。
实现这个的方法有很多种,但基本上它们都是一样的,你所做的就是用 window 中需要刷新的对象的名称调用 PropertyChanged 事件。
PropertyChanged 事件关闭并通知 window 更新。
如有任何问题,请随时提出。
Window.xaml:
<Window x:Class="WPF_Label_Update.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:WPF_Label_Update"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="The_WPF_Grid">
<Grid.DataContext>
<local:My_View_Model/>
</Grid.DataContext>
<Grid.Resources>
<DataTemplate x:Key="myDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Path=obj_name}" />
</StackPanel>
</DataTemplate>
</Grid.Resources>
<StackPanel Orientation="Horizontal">
<ListBox x:Name="list_choice"
SelectedItem="{Binding My_Selected_Object}"
SelectionMode="Single"
ItemsSource="{Binding My_Objects}"
ItemTemplate="{StaticResource myDataTemplate}">
</ListBox>
<StackPanel Orientation="Vertical">
<Label x:Name="lbl_output_0" Content="{Binding Label_Text_0}"/>
<Label x:Name="lbl_output_1" Content="{Binding Label_Text_1}"/>
<Label x:Name="lbl_output_2" Content="{Binding Label_Text_2}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPF_Label_Update
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
My_View_Model myViewModel;
private void generateData()
{
StringBuilder _text = new StringBuilder() ;
for (int i = 0; i < 10; i++)
{
_text.Clear();
_text.Append($"Number {i}");
for (int ii = 0; ii < i; ii++)
{
_text.Append($"|{ii}");
}
myViewModel.Add_Item(new my_obj(_text.ToString()));
}
}
public MainWindow()
{
InitializeComponent();
myViewModel =
new My_View_Model();
this.The_WPF_Grid.DataContext = myViewModel;
generateData();
}
private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Something Was Selected");
}
}
}
My_View_Model.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace WPF_Label_Update
{
public class My_View_Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Label_Text_0 { get { return lbl0; } set { lbl0 = value; OnPropertyChanged(); } }
private string lbl0 = string.Empty;
public string Label_Text_1 { get { return lbl1; } set { lbl1 = value; OnPropertyChanged(); } }
private string lbl1 = string.Empty;
public string Label_Text_2 { get { return lbl2; } set { lbl2 = value; OnPropertyChanged(); } }
private string lbl2 = string.Empty;
public my_obj My_Selected_Object {
get {
return mySelectedObj;
}
set {
mySelectedObj = value;
on_mySelectedObjChange();
} }
private my_obj mySelectedObj = null;
/// <summary>
/// Update lables when something changes.
/// </summary>
private void on_mySelectedObjChange()
{
switch (mySelectedObj == null)
{
case true:
Label_Text_0 = string.Empty;
Label_Text_1 = string.Empty;
Label_Text_2 = string.Empty;
break;
default:
Label_Text_0 = mySelectedObj.obj_text;
Label_Text_1 = mySelectedObj.obj_name;
Label_Text_2 = mySelectedObj.obj_count.ToString();
break;
}
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public ObservableCollection<my_obj> My_Objects { get { return my_objs; } }
private readonly ObservableCollection<my_obj> my_objs = new ObservableCollection<my_obj>();
public void Add_Item(my_obj new_obj)
{
my_objs.Add(new_obj);
}
public My_View_Model()
{
}
}
public class my_obj
{
public string obj_text { get; set; }
public string obj_name { get { return obj_text.Split('|')[0]; } }
public int obj_count { get { return obj_text.Split('|').Length; } }
public my_obj(string inputText)
{
this.obj_text = inputText.Trim();
}
}
}
我得到它来处理这个 - 谢谢大家
private void lstStudents_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstStudents.SelectedIndex != -1)
{
string student =
(string)studentScores[lstStudents.SelectedIndex];
string[] scores = student.Split('|');
int total = 0;
for (int i = 1; i < scores.Length; i++)
total += Convert.ToInt32(scores[i]);
int count = scores.Length - 1;
int average = 0;
if (total > 0)
average = total / count;
lblScoreTotal.Text = total.ToString();
lblScoreCount.Text = count.ToString();
lblAverage.Text = average.ToString();
}
}