WPF主窗口加载文件名至用户控件ListBox失效问题求助
问题根源
每次点击Object_placement按钮时,都会新建一个UserControl1实例并添加到settingpanel,但loadbtn_Click里操作的myUserControl是全局变量,它指向的是之前创建的旧实例(或者根本不是当前显示的那个),所以文件名加不到当前界面的ListBox里。而Direct Load能正常工作,应该是它操作的是同一个未被替换的实例。
解决方案
方法1:保存当前实例的引用
修改按钮点击逻辑,把新创建的UserControl1实例存到全局变量里,后续Load按钮直接操作这个变量:
// 在窗口类里声明全局变量 private UserControl1 currentUserControl; private void Object_placement_Click(object sender, RoutedEventArgs e) { settingpanel.Children.Clear(); currentUserControl = new UserControl1(); settingpanel.Children.Add(currentUserControl); } private void loadbtn_Click(object sender, RoutedEventArgs e) { // 原文件处理代码保持不变... // 替换myUserControl为currentUserControl,先判空避免异常 if(currentUserControl != null) { string stlFileName = Path.GetFileNameWithoutExtension(Stlfilpath); currentUserControl.objectListBox.Items.Add(stlFileName); } }
注意:要让主窗口能访问UserControl1里的objectListBox,得在UserControl1的XAML里把ListBox的x:FieldModifier设为public或internal:
<ListBox x:Name="objectListBox" x:FieldModifier="public" />
方法2:从容器中查找当前实例
如果不想用全局变量,可以在Load按钮点击时,直接从settingpanel里找出当前的UserControl1实例:
private void loadbtn_Click(object sender, RoutedEventArgs e) { // 原文件处理代码保持不变... // 从settingpanel的子控件中筛选出UserControl1实例 var currentUserControl = settingpanel.Children.OfType<UserControl1>().FirstOrDefault(); if(currentUserControl != null) { string stlFileName = Path.GetFileNameWithoutExtension(Stlfilpath); currentUserControl.objectListBox.Items.Add(stlFileName); } }
同样需要给objectListBox设置x:FieldModifier属性。
方法3:用MVVM数据绑定(推荐的WPF写法)
直接操作控件不符合WPF的设计思路,更规范的方式是用数据绑定:
- 在
UserControl1里定义一个可观察集合作为数据源:
public class UserControl1 : UserControl { public ObservableCollection<string> FileNames { get; set; } public UserControl1() { InitializeComponent(); FileNames = new ObservableCollection<string>(); objectListBox.ItemsSource = FileNames; } }
- 在UserControl1的XAML里绑定ListBox的数据源:
<ListBox x:Name="objectListBox" ItemsSource="{Binding FileNames, RelativeSource={RelativeSource AncestorType=UserControl}}" />
- 主窗口里操作实例的集合:
private UserControl1 currentUserControl; private void Object_placement_Click(object sender, RoutedEventArgs e) { settingpanel.Children.Clear(); currentUserControl = new UserControl1(); settingpanel.Children.Add(currentUserControl); } private void loadbtn_Click(object sender, RoutedEventArgs e) { // 原文件处理代码保持不变... if(currentUserControl != null) { string stlFileName = Path.GetFileNameWithoutExtension(Stlfilpath); currentUserControl.FileNames.Add(stlFileName); } }
这种方式不需要修改控件的访问权限,代码更易维护,也符合WPF的设计模式。
内容的提问来源于stack exchange,提问作者user21346702
相关产品推荐
相关产品推荐

