Wpf 动态添加元素上的绑定

Wpf 动态添加元素上的绑定,wpf,xaml,Wpf,Xaml,TPTB已决定我们的应用程序必须在单个窗口中运行,不允许在模式模式下弹出新窗口 当然,我们有一个UI设计,包括在所有地方弹出模态对话框 因此,我在窗口中添加了一个顶级网格。在该网格中,我没有定义行或列,因此所有内容都在第0行/第0列中绘制 网格中的第一个元素是另一个网格,它包含窗口中通常显示的所有内容。第二个是全尺寸边框,背景为灰色半透明。其余的是宽边距和白色背景的边框,包含需要显示为弹出窗口的各种用户控件。除了第一个,其他所有的都已经崩溃了 然后,当我需要显示弹出窗口时,我会在灰色背景和相应的

TPTB已决定我们的应用程序必须在单个窗口中运行,不允许在模式模式下弹出新窗口

当然,我们有一个UI设计,包括在所有地方弹出模态对话框

因此,我在窗口中添加了一个顶级网格。在该网格中,我没有定义行或列,因此所有内容都在第0行/第0列中绘制

网格中的第一个元素是另一个网格,它包含窗口中通常显示的所有内容。第二个是全尺寸边框,背景为灰色半透明。其余的是宽边距和白色背景的边框,包含需要显示为弹出窗口的各种用户控件。除了第一个,其他所有的都已经崩溃了

然后,当我需要显示弹出窗口时,我会在灰色背景和相应的用户控件上设置Visibility=“Visible”。结果是一个很好的阴影盒效果,效果很好

直到有人决定弹出窗口需要能够显示弹出窗口。以不可预测的顺序

我在网格中使用Visibility=“Collapsed”元素实现的方法的局限性在于它们的顺序是固定的。UserControlB将始终显示在UserControlA的顶部,即使是UserControlB要求显示UserControlA。这是不可接受的

因此,我的下一次尝试是在Window.Resources中定义各种UserControls,并在代码中将它们添加到网格中:

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