Wpf 动态添加元素上的绑定
TPTB已决定我们的应用程序必须在单个窗口中运行,不允许在模式模式下弹出新窗口 当然,我们有一个UI设计,包括在所有地方弹出模态对话框 因此,我在窗口中添加了一个顶级网格。在该网格中,我没有定义行或列,因此所有内容都在第0行/第0列中绘制 网格中的第一个元素是另一个网格,它包含窗口中通常显示的所有内容。第二个是全尺寸边框,背景为灰色半透明。其余的是宽边距和白色背景的边框,包含需要显示为弹出窗口的各种用户控件。除了第一个,其他所有的都已经崩溃了 然后,当我需要显示弹出窗口时,我会在灰色背景和相应的用户控件上设置Visibility=“Visible”。结果是一个很好的阴影盒效果,效果很好 直到有人决定弹出窗口需要能够显示弹出窗口。以不可预测的顺序 我在网格中使用Visibility=“Collapsed”元素实现的方法的局限性在于它们的顺序是固定的。UserControlB将始终显示在UserControlA的顶部,即使是UserControlB要求显示UserControlA。这是不可接受的 因此,我的下一次尝试是在Window.Resources中定义各种UserControls,并在代码中将它们添加到网格中:Wpf 动态添加元素上的绑定,wpf,xaml,Wpf,Xaml,TPTB已决定我们的应用程序必须在单个窗口中运行,不允许在模式模式下弹出新窗口 当然,我们有一个UI设计,包括在所有地方弹出模态对话框 因此,我在窗口中添加了一个顶级网格。在该网格中,我没有定义行或列,因此所有内容都在第0行/第0列中绘制 网格中的第一个元素是另一个网格,它包含窗口中通常显示的所有内容。第二个是全尺寸边框,背景为灰色半透明。其余的是宽边距和白色背景的边框,包含需要显示为弹出窗口的各种用户控件。除了第一个,其他所有的都已经崩溃了 然后,当我需要显示弹出窗口时,我会在灰色背景和相应的
this.masterGrid.Children.Add(this.Resources["userControlA"] as UserControlA);
这几乎奏效了。但是绑定都是乱七八糟的
例如,其中一个控件应该将属性绑定到窗口的viewmodel的成员对象中集合的CurrentItem。当我将控件定义为网格中的不可见项时,它工作得很好。但当我将其定义为资源时,该属性为null——它从未绑定
因此,在将其添加到网格后,我尝试将其绑定到代码中:
userControlA.SetBinding(UserControlA.myProperty, new Binding()
{ Source = this.viewModel.myCollection.CurrentItem });
这可以很好地编译和运行,但我没有绑定到正确的对象
第一次显示UserControl时,我看到绑定到它的正确对象。但是当我关闭它,将集合中的CurrentItem移动到另一个对象,并再次显示UserControl时,我仍然看到第一个对象绑定。如果我再次关闭它,并再次打开它,那么我将看到绑定到控件的正确对象
我已经签入了代码,我绑定到的CurrentItem每次都是正确的,但它似乎每隔一次才生效
因此,我尝试明确地清除绑定,首先:
BindingOperations.ClearBinding(userControlA, UserControlA.myProperty);
userControlA.SetBinding(UserControlA.myProperty, new Binding()
{ Source = this.viewModel.myCollection.CurrentItem });
但这似乎没有任何区别
总的来说,我感觉自己像是在跑进一个兔子洞,一步一步地追求复杂性,去解决一个应该相当简单的问题
是否有人对以下方面有任何建议:
提前谢谢。虽然你不能创建新窗口对我来说真的很奇怪,但我绝对建议不要做不必要的事情,比如将视图存储在主窗口的资源中,从而使它变得太复杂 如果您只是将这些元素的新实例添加到ObservableCollection中会更好: XAML:
代码隐藏:
using System.Linq;
using System.Windows;
using System.Collections.ObjectModel;
using System;
namespace WpfApplication4
{
public partial class Window8 : Window
{
private WidgetsViewModel Widgets { get; set; }
public Window8()
{
InitializeComponent();
DataContext = Widgets = new WidgetsViewModel();
}
private Random rnd = new Random();
private int lastrandom;
private void Add_Click(object sender, RoutedEventArgs e)
{
var random = rnd.Next(1, 4);
while (random == lastrandom)
{
random = rnd.Next(1, 4);
}
lastrandom = random;
switch (random)
{
case 1:
Widgets.ActiveWidgets.Add(new ViewModel1() {Text = "This is a Text"});
break;
case 2:
Widgets.ActiveWidgets.Add(new ViewModel2() { Text2 = "This is another Text" });
break;
case 3:
Widgets.ActiveWidgets.Add(new ViewModel3() { Text3 = "This is yet another Text" });
break;
}
Widgets.SelectedWidget = Widgets.ActiveWidgets.LastOrDefault();
}
private void Remove_Click(object sender, RoutedEventArgs e)
{
Widgets.ActiveWidgets.Remove(Widgets.SelectedWidget);
Widgets.SelectedWidget = Widgets.ActiveWidgets.LastOrDefault();
}
}
public class WidgetsViewModel: ViewModelBase
{
public ObservableCollection<ViewModelBase> ActiveWidgets { get; set; }
private ViewModelBase _selectedWidget;
public ViewModelBase SelectedWidget
{
get { return _selectedWidget; }
set
{
_selectedWidget = value;
NotifyPropertyChange(() => SelectedWidget);
}
}
public WidgetsViewModel()
{
ActiveWidgets = new ObservableCollection<ViewModelBase>();
}
}
public class ViewModel1: ViewModelBase
{
public string Text { get; set; }
}
public class ViewModel2: ViewModelBase
{
public string Text2 { get; set; }
}
public class ViewModel3: ViewModelBase
{
public string Text3 { get; set; }
}
}
使用System.Linq;
使用System.Windows;
使用System.Collections.ObjectModel;
使用制度;
命名空间WpfApplication4
{
公共部分类Window8:Window
{
私有WidgetsViewModel小部件{get;set;}
公共窗口8()
{
初始化组件();
DataContext=Widgets=newwidgetsviewmodel();
}
私有随机rnd=新随机();
私密的、随机的;
私有无效添加\单击(对象发送者,路由目标)
{
var random=rnd.Next(1,4);
while(random==lastrandom)
{
random=rnd.Next(1,4);
}
lastrandom=随机;
开关(随机)
{
案例1:
Widgets.ActiveWidgets.Add(新的ViewModel1(){Text=“这是一个文本”});
打破
案例2:
Widgets.ActiveWidgets.Add(newviewmodel2(){Text2=“这是另一个文本”});
打破
案例3:
Widgets.ActiveWidgets.Add(新的ViewModel3(){Text3=“这是另一个文本”});
打破
}
Widgets.SelectedWidget=Widgets.ActiveWidgets.LastOrDefault();
}
私有无效删除\单击(对象发送方,路由目标)
{
Widgets.ActiveWidgets.Remove(Widgets.SelectedWidget);
Widgets.SelectedWidget=Widgets.ActiveWidgets.LastOrDefault();
}
}
公共类WidgetsViewModel:ViewModelBase
{
公共ObservableCollection ActiveWidgets{get;set;}
私有ViewModelBase _selectedWidget;
公共ViewModelBase SelectedWidget
{
获取{return\u selectedWidget;}
设置
{
using System.Linq;
using System.Windows;
using System.Collections.ObjectModel;
using System;
namespace WpfApplication4
{
public partial class Window8 : Window
{
private WidgetsViewModel Widgets { get; set; }
public Window8()
{
InitializeComponent();
DataContext = Widgets = new WidgetsViewModel();
}
private Random rnd = new Random();
private int lastrandom;
private void Add_Click(object sender, RoutedEventArgs e)
{
var random = rnd.Next(1, 4);
while (random == lastrandom)
{
random = rnd.Next(1, 4);
}
lastrandom = random;
switch (random)
{
case 1:
Widgets.ActiveWidgets.Add(new ViewModel1() {Text = "This is a Text"});
break;
case 2:
Widgets.ActiveWidgets.Add(new ViewModel2() { Text2 = "This is another Text" });
break;
case 3:
Widgets.ActiveWidgets.Add(new ViewModel3() { Text3 = "This is yet another Text" });
break;
}
Widgets.SelectedWidget = Widgets.ActiveWidgets.LastOrDefault();
}
private void Remove_Click(object sender, RoutedEventArgs e)
{
Widgets.ActiveWidgets.Remove(Widgets.SelectedWidget);
Widgets.SelectedWidget = Widgets.ActiveWidgets.LastOrDefault();
}
}
public class WidgetsViewModel: ViewModelBase
{
public ObservableCollection<ViewModelBase> ActiveWidgets { get; set; }
private ViewModelBase _selectedWidget;
public ViewModelBase SelectedWidget
{
get { return _selectedWidget; }
set
{
_selectedWidget = value;
NotifyPropertyChange(() => SelectedWidget);
}
}
public WidgetsViewModel()
{
ActiveWidgets = new ObservableCollection<ViewModelBase>();
}
}
public class ViewModel1: ViewModelBase
{
public string Text { get; set; }
}
public class ViewModel2: ViewModelBase
{
public string Text2 { get; set; }
}
public class ViewModel3: ViewModelBase
{
public string Text3 { get; set; }
}
}