精华内容
下载资源
问答
  • MVVM WPF 动态添加控件及绑定
    千次阅读
    2020-02-18 11:15:04

    现在有这么一个需求,需要动态添加自定义控件到界面,自定义控件数量不固定,内容是通过服务获取的,以前是做winform的,winform简单,直接 new自定义控件添加上去就行,现在wpf mvvm模式,不知道怎么做了,能否在viewmodel中添加一个 observablecollection,界面绑定这个属性,界面自动生成这么多个自定义控件?如果可以,各位大佬能否提供下实现思路,有个demo什 么的最好了。


    <Window x:Class="WpfApplication5.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <!--控件模板-->
            <DataTemplate x:Key="UserDataTemplate">
              
                <Border BorderThickness="2" BorderBrush="Black" Margin="2">
                    <StackPanel>
                        <Image />
                        <Label HorizontalAlignment="Center" Content="{Binding Path=Name}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
        </Window.Resources>
        <Grid Name="mygrid">
            <!--容器-->
            <ItemsControl x:Name="testList" ItemTemplate="{StaticResource UserDataTemplate}" ItemsSource="{Binding Btns}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </Grid>
    </Window>


    using System;
    using System.Collections.Generic;
    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 WpfApplication5
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
           public MainWindowViewModel user { get; set; }
            public MainWindow()
            {
                InitializeComponent();
                user = new MainWindowViewModel();
                mygrid.DataContext = user;//指定ViewModel
            }

        }
    }


    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Controls;

    namespace WpfApplication5
    {
        public class MainWindowViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public MainWindowViewModel()
            {
                Btns = new ObservableCollection<Item>() { new Item(){Name = "测试1"}, new Item(){Name = "测试2"} };
            }


            private ObservableCollection<Item> btns;

            public ObservableCollection<Item> Btns
            {
                get { return btns; }
                set { btns = value; }
            }
        }  
    }


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace WpfApplication5
    {
        public class Item : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;

            private string _name;
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Name"));
                    }
                }
            }
        }
    }

    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local ="clr-namespace:WpfApp1"
            Title="MainWindow" Height="450" Width="800">
      <Window.Resources>
        <DataTemplate DataType="{x:Type local:MyContract}"> <!-- 类型是MyContract的,用这个模板 -->
          <StackPanel Width="128" Height="150" Margin="20">
            <Image Source="{Binding ImageUrl}" />
            <TextBlock Text="{Binding Name}" />
          </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:MyCard}"><!-- 类型是MyCard的,用这个模板 -->
          <Grid Width="128" Height="150" Margin="20" Background="{Binding Color}">
            <TextBlock Text="{Binding Color}" FontSize="24" VerticalAlignment="Center" />
          </Grid>
        </DataTemplate>
      </Window.Resources>
      <Grid>
        <ItemsControl ItemsSource="{Binding Items}" > <!-- 不直接指定模板,而是用数据类型来决定 -->
          <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate><WrapPanel IsItemsHost="True" /></ItemsPanelTemplate>
          </ItemsControl.ItemsPanel>
        </ItemsControl>
      </Grid>
    </Window>

    using System.Collections.ObjectModel;
    using System.Windows;
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                Items = new ObservableCollection<object>()
                {
                    new MyContract(){ Name = "杀马特丶蛮牛", ImageUrl = "https://profile.csdnimg.cn/A/3/4/1_zhengbingfe"},
                    new MyContract(){ Name = "正怒月神", ImageUrl = "https://profile.csdnimg.cn/F/F/E/1_hanjun0612"},
                    new MyContract(){ Name = "OrdinaryCoder", ImageUrl = "https://profile.csdnimg.cn/6/0/9/1_weixin_40440974"},
                    new MyCard() { Color = "PeachPuff"},
                    new MyCard() { Color = "SeaShell"},
                    new MyCard() { Color = "SteelBlue"},
                };
                this.DataContext = this;
            }
            public ObservableCollection<object> Items { get; }
        }
        public class MyContract // 可自行实现INotifyPropertyChanged接口
        {
            public string Name { get; set; }
            public string ImageUrl { get; set; }
        }
        public class MyCard
        {
            public string Color { get; set; }
        }
    }

     

    另外,数据模板的强处,在于它可以利用数据类型,来决定具体的展示模板。还小蜜蜂论坛发帖机可以这么用

    更多相关内容
  • 实现的效果如下:之前的思路,就是建立一个singleKey的控件,然后在后台用代码动态添加到父控件里去, 再用代码在后台进行绑定。这种实现方法并不是真正的MVVM的模式。体会不到MVVM带来的便捷和惊喜。用MVVM模式来...

    比如需要显示一个键盘,里面有各个按键。实现的效果如下:

    之前的思路,就是建立一个singleKey的控件,然后在后台用代码动态的添加到父控件里去, 再用代码在后台进行绑定。

    这种实现方法并不是真正的MVVM的模式。体会不到MVVM带来的便捷和惊喜。

    用MVVM模式来实现时的思路如下:

    1. 建立singleKey的ViewModel,定义需要绑定View的属性。

    2. 在Key的ViewModel中,使用可观察集合,并绑定到View的ItemsSource上。

    ViewModel

    public ObservableCollectionKeysets

    {get{return this.keysets;

    }set{this.keysets =value;

    }

    }

    3. 对于singleKey的显示,可以在DataTemplat里面定义。

    View

    >

    于是,并不用在后台写过多的代码,修改ViewModel后, View的显示就相应变更了。

    补充网上大牛的回复。

    if you really want to do mvvm , try to forget "how can i add controls". you dont have to, just think about your viewmodels - WPF create the contols for you :)

    in your case lets say we have a SearchViewModel and a SearchEntryViewmodel.

    publicclassSearchEntryViewmodel{//Properties for Binding to Combobox and Textbox goes here}publicclassSearchViewModel{publicObservableCollectionMySearchItems{get;set;}publicICommandAddSearchItem{get;}}

    till now you dont have to think about usercontrols/view. in your SearchView you create an ItemsControl and bind the ItemsSource to MySearchItems.

    you see now all of your SearchEntryViewmodels in the ItemsControl(just the ToString() atm).

    To fit your requirements to show every SearchEntryViewmodel with 3Comboboxes and so on you just have to define a DataTemplate in your Resources

    thats all :) and you never has to think about how can i add controls dynamically. you just have to add new SearchEntryViewmodel to your collection.

    this approach is called Viewmodel First and i think its the easiest way to do MVVM.

    在实践发现,通用的方法还是创建一个userControl view,重要的是再DataTemplate里面引用:

    展开全文
  • 主要为大家详细介绍了MVVM模式下WPF动态绑定展示图片的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • WPF MVVM 动态创建控件

    热门讨论 2011-11-16 10:32:07
    在有一些项目中,UI界面上的控件有时是在程序运行时才生成的。这样的功能在MVVM中也很容易实现。并且可以通过按钮取得其值。  本实例主要实现程序运行时,在界面上生成四个控件,两个TextBox和两个TextBlock.并且...
  • WPF实现MVVM的事件绑定

    2019-01-17 20:30:34
    WPF实现MVVM的事件绑定的两种非常规方式。 参考博客:https://blog.csdn.net/IQQQQU/article/details/86530285 1、重写InvokeCommandAction来扩充返回的参数 2、运用Behavior来实现事件,可以通过两种方式来获取...
  • WPF MVVM 循环添加控件

    2021-06-27 16:46:49
    WPF里面使用MVVM模式实现跨页面传输ID,并且查询出相应的数据 首先我们需要创建一个用户控件,当然你也一直接在那个主页面给他几个按钮,然后点击按钮就会传输特定的值,不过因为你这些值不是通过数据库查询出来的...

    在WPF里面使用MVVM模式实现跨页面传输ID,并且查询出相应的数据
    首先我们需要创建一个用户控件,当然你也一直接在那个主页面给他几个按钮,然后点击按钮就会传输特定的值,不过因为你这些值不是通过数据库查询出来的,没有办法随时改变想要的数据,比较生硬,我这边的话是先创建一个用户控件,里面就一个按钮,然后按钮的名称是通过绑定,在数据库查询出来的。

    <Border Background="Transparent">
            <Grid>
                <TextBlock Text="{Binding Commodity_category_ID}" Visibility="Collapsed"/>
                <Button  FontSize="15" FontFamily="宋体"  Style="{StaticResource  BtnHuiLFillStyle}"
                           Command="{Binding BtnClickCommand}"         Content="{Binding txt_ButtonName}" ContextMenu="{StaticResource ContextMenu}" />
            </Grid>
    </Border>
    

    上面是用户控件里面的内容,就放了一个按钮,然后去到主页面,他是和按钮是不同一个页面的,

    <ScrollViewer Grid.Row="1" Background="White">
                            <StackPanel Name="wp_Simers" Orientation="Vertical">
    
                            </StackPanel>
                        </ScrollViewer>
    

    写上这个控件,等下需要把按钮的用户控件在ViewModel通过代码循环添加到这个里面

    上面是添加控件的代码

        /// <summary>
            /// 查询并添加左边菜单栏按钮
            /// </summary>
            /// 
            public void SelectleftButton(UserControl uc)
            {
                try
    
                {
                    UserControl myuc = (UserControl)uc;
                    UC = myuc;
                    DependencyObject parent = VisualTreeHelper.GetParent(myuc);
                    //获取StackPanel控件 集合      
                    List<StackPanel> mySP = FindVisualChildren.FindVisualChildrens<StackPanel>(parent);
                    SP = mySP[0];
                    //清空控件里面的内容
                    if (SP != null)
                    {
                        SP.Children.Clear();
                    }
                    var listCommodityType = (from tb in myModel.B_Commodity_category
                                             select new
                                             {
                                                 Commodity_category_id = tb.Commodity_category_id,
                                                 Commodity_category = tb.Commodity_category
                                             }
                                          ).ToList();
                    dataTable = ListToDataTable.ListToDataTablen(listCommodityType);
                    if (dataTable != null)
                    {
                        //用for循环添加按钮控件
                        for (int i = 0; i < dataTable.Rows.Count; i++)
                        {
                            //实例化桌子,把它添加到StackPanel里面
                            Commodity_button_UC commodit_Button_UC = new Commodity_button_UC();
    
                            int Commodity_category_id = Convert.ToInt32(dataTable.Rows[i]["Commodity_category_id"].ToString());
                            var Commodity_buttonUCModel = (commodit_Button_UC.DataContext as Commodity_buttonUCModel);
                            Commodity_buttonUCModel.Commodity_category_ID = Commodity_category_id;
                            Commodity_buttonUCModel.LeftButton += Item_Commodity_button;
                            SP.Children.Add(commodit_Button_UC);
                            Commodity_buttonUCModel.ChangeTextEvent += new Commodity_buttonUCModel.ChangeTextHandler(selectlist);
                        }
                    }
                }
                catch (Exception ex)
                {
    
                    Debug.WriteLine(ex);
                }
            }
    

    UserControl myuc = (UserControl)uc;
    UC = myuc;
    DependencyObject parent = VisualTreeHelper.GetParent(myuc);
    //获取StackPanel控件 集合
    List mySP = FindVisualChildren.FindVisualChildrens(parent);
    SP = mySP[0];
    首先使用查询视觉树的方法,通过视觉树查到到ScrollViewer控件里面的StackPanel,查到之后就把这个控件赋值给一个全局变量SP,之后判断SP里面是不是空的,不是就清空里面的内容,之后就是把你用LinQ查询到的内容转换成dataTable格式,下面需要这个格式获取到某一列的ID,判断这个表格是不是为空,如果他不为空的话,就通过for循环去添加。
    Commodity_button_UC commodit_Button_UC = new Commodity_button_UC();先实例化你的按钮的那个页面,然后通过var Commodity_buttonUCModel = (commodit_Button_UC.DataContext as Commodity_buttonUCModel);声明他属于哪个ViewModel,接下来的两步就是把这个按钮的ID传输到你按钮的那个页面的ViewModel里面,在那边是有可以接收通知的那种属性写法来接收,Commodity_buttonUCModel.Commodity_category_ID = Commodity_category_id;
    按钮页面的接收用

    //接收主键ID
            private int _Commodity_category_ID;
            public int Commodity_category_ID
            {
                get { return _Commodity_category_ID; }
                set
                {
                    if (_Commodity_category_ID != value)
                    {
                        _Commodity_category_ID = value;
                        RaisePropertyChanged(() => Commodity_category_ID);
    
                    }
                }
            }
    

    Commodity_buttonUCModel.LeftButton += Item_Commodity_button;
    而Item_Commodity_button这个是一个方法,这个方法里面放的是上面图片的方法,因为我需要用委托把这个方法本身传过去以到达如果我对按钮做出删除或者修改里面内容的操作就更新,按钮那边需要声明委托来接收这个方法,LeftButton就是按钮那边页面声明的委托

    public delegate void UpdateCompletedEventHandler();
            public event UpdateCompletedEventHandler LeftButton;
    

    SP.Children.Add(commodit_Button_UC);而这一步就是把按钮添加到主页面的StackPanel里面
    左边的类别就是效果图

    展开全文
  • 主要采用了Prism.DryIoc的MVVM方式,用到控件和方法:ItemsControl(控件模板)、Thumb(可拖动控件)、Adorner(装饰器)、CommandParameter的多参数传递、GetChildObjectByUid(通过UID查找某类型的子控件)这个类...

    WPF Prism MVVM【动态添加控件并可用鼠标、拖动、缩放、旋转】


    前言

    本文中所开发的功能是为了给后台目标检测算法做区域标注的一个Demo。为视频中标注电子围栏和框选区域。主要采用了Prism.DryIoc的MVVM方式,用到控件和方法:ItemsControl(控件模板)、Thumb(可拖动控件)、Adorner(装饰器)、CommandParameter的多参数传递、GetChildObjectByUid(通过UID查找某类型的子控件)

    项目运行截图


    一、基本类

    1.控件对应的实体类

    这个类只是为了给生成的控件一个数据的支撑(可以理解为灵魂:😜)

    using Prism.Commands;
    using Prism.Mvvm;
    namespace BlankApp2
    {
        public class ObjEntity : BindableBase
        {
            public int ID { get; set; }      
            /// <summary>
            /// 节点名称
            /// </summary>
            public string Name { set; get; }
            /// <summary>
            /// 拖动事件
            /// </summary>
            public DelegateCommand<object> onDragDeltaCommand { get; set; }
            /// <summary>
            /// 控件加载后事件
            /// </summary>
            public DelegateCommand<object> onThumbLoadedCommand { get; set; }
        }
    }
    

    2.控件缩放和旋转的核心类

    GridAdorner(Grid装饰器)这个类主要是在动态添加到前端的Loaded事件中为其添加上一些Thumb控件,并且用鼠标操作这些Thumb来调整其控件的大小和旋转。

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Shapes;
    namespace BlankApp2
    {
        /// <summary>
        /// Grid装饰器
        /// </summary>
        public class GridAdorner : Adorner
        {
            //4条边
            Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
            //4个角
            Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
    
            Thumb _middleThumb;
            //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
            Grid _grid;
            UIElement _adornedElement;
            public GridAdorner(UIElement adornedElement) : base(adornedElement)
            {           
                _adornedElement = adornedElement;
                //初始化四周和中间的thumb
                _middleThumb = new Thumb();
                _middleThumb.HorizontalAlignment = HorizontalAlignment.Center;
                _middleThumb.VerticalAlignment = VerticalAlignment.Center;
                _middleThumb.Cursor =Cursors.Cross;
         
                  _leftThumb = new Thumb();
                _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
                _leftThumb.VerticalAlignment = VerticalAlignment.Center;
                _leftThumb.Cursor = Cursors.SizeWE;
                _topThumb = new Thumb();
                _topThumb.HorizontalAlignment = HorizontalAlignment.Center;
                _topThumb.VerticalAlignment = VerticalAlignment.Top;
                _topThumb.Cursor = Cursors.SizeNS;
                _rightThumb = new Thumb();
                _rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
                _rightThumb.VerticalAlignment = VerticalAlignment.Center;
                _rightThumb.Cursor = Cursors.SizeWE;
                _bottomThumb = new Thumb();
                _bottomThumb.HorizontalAlignment = HorizontalAlignment.Center;
                _bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
                _bottomThumb.Cursor = Cursors.SizeNS;
                _lefTopThumb = new Thumb();
                _lefTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
                _lefTopThumb.VerticalAlignment = VerticalAlignment.Top;
                _lefTopThumb.Cursor = Cursors.SizeNWSE;
                _rightTopThumb = new Thumb();
                _rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
                _rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
                _rightTopThumb.Cursor = Cursors.SizeNESW;
                _rightBottomThumb = new Thumb();
                _rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
                _rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
                _rightBottomThumb.Cursor = Cursors.SizeNWSE;
                _leftbottomThumb = new Thumb();
                _leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
                _leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
                _leftbottomThumb.Cursor = Cursors.SizeNESW;
    
    
                _grid = new Grid();           
                _grid.Children.Add(_middleThumb);
                _grid.Children.Add(_leftThumb);
                _grid.Children.Add(_topThumb);
                _grid.Children.Add(_rightThumb);
                _grid.Children.Add(_bottomThumb);
                _grid.Children.Add(_lefTopThumb);
                _grid.Children.Add(_rightTopThumb);
                _grid.Children.Add(_rightBottomThumb);
                _grid.Children.Add(_leftbottomThumb);
                AddVisualChild(_grid);
    
                foreach (Thumb thumb in _grid.Children)
                {
                    thumb.Width = 13;
                    thumb.Height = 13;
                    thumb.Background = Brushes.Green;
                    thumb.Template = new ControlTemplate(typeof(Thumb))
                    {
                        VisualTree = GetFactory(new SolidColorBrush(Colors.White))
                    };
                    thumb.DragDelta += Thumb_DragDelta;            
                }
            }
           /// <summary>
           /// 控件的旋转事件
           /// </summary>
           /// <param name="sender"></param>
           /// <param name="e"></param>
            private void _zhongThumb_MouseMove(object sender, MouseEventArgs e)
            {           
                if (Mouse.Captured == _adornedElement)
                {
                    double a = Math.PI;
                    var c = _adornedElement as FrameworkElement;
                   // c.RenderTransformOrigin = new Point(0.5, 0.5);
                    // Get the current mouse position relative to the volume control
                    Point currentLocation = Mouse.GetPosition(this);
    
                    // We want to rotate around the center of the knob, not the top corner
                    Point knobCenter = new Point(this.ActualHeight / 2, this.ActualWidth / 2);
    
                    // Calculate an angle
                    //double radians = Math.Atan((currentLocation.Y - knobCenter.Y) /
                    //                           (currentLocation.X - knobCenter.X));
                    double radians = Math.Atan((currentLocation.Y)/
                                          (currentLocation.X));
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = radians * 180 / Math.PI;
                    rt.Angle = radians ;
                    // Apply a 180 degree shift when X is negative so that we can rotate
                    // all of the way around
                    //if (currentLocation.X - knobCenter.X < 0)
                    //{
                    //    rt.Angle += 180;
                    //}
                    c.RenderTransform = rt;
                  //  c.RenderTransformOrigin = new Point(0, 0);
                }
            }
            /// <summary>
            /// 鼠标在旋转控件上抬起
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void _zhongThumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                Mouse.Capture(null);
            }
            /// <summary>
            /// 鼠标在旋转控件上按下
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void _zhongThumb_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                Mouse.Capture(this);
            }
            protected override Visual GetVisualChild(int index)
            {
                return _grid;
            }
            protected override int VisualChildrenCount
            {
                get
                {
                    return 1;
                }
            }
            protected override Size ArrangeOverride(Size finalSize)
            {            //直接给grid布局,grid内部的thumb会自动布局。
                _grid.Arrange(new Rect(new Point(-_leftThumb.Width / 2, -_leftThumb.Height / 2), new Size(finalSize.Width + _leftThumb.Width, finalSize.Height + _leftThumb.Height)));
                return finalSize;
            }
            /// <summary>
            /// 拖动事件逻辑
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
            {
                var c = _adornedElement as FrameworkElement;
                var thumb = sender as FrameworkElement;
                double left, top, right, bottom, width, height;
                if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
                {
                    right = c.Margin.Right;
                    left = c.Margin.Left + e.HorizontalChange;
                    width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) - e.HorizontalChange;
                }
                else
                {
                    left = c.Margin.Left;
                    right = c.Margin.Right - e.HorizontalChange;
                    width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width) + e.HorizontalChange;
                }
    
                if (thumb.VerticalAlignment == VerticalAlignment.Top)
                {
                    bottom = c.Margin.Bottom;
                    top = c.Margin.Top + e.VerticalChange;
                    height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) - e.VerticalChange;
                }
                else
                {
                    top = c.Margin.Top;
                    bottom = c.Margin.Bottom - e.VerticalChange;
                    height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) + e.VerticalChange;
                }
                if (thumb.HorizontalAlignment != HorizontalAlignment.Center)
                {
                    if (width >= 0)
                    {
                        c.Margin = new Thickness(left, c.Margin.Top, right, c.Margin.Bottom);
                        c.Width = width;
                    }
                }
                if (thumb.VerticalAlignment != VerticalAlignment.Center)
                {
                    if (height >= 0)
                    {
                        c.Margin = new Thickness(c.Margin.Left, top, c.Margin.Right, bottom);
                        c.Height = height;
                    }
                }
                if (thumb.HorizontalAlignment == HorizontalAlignment.Center && thumb.VerticalAlignment == VerticalAlignment.Center)
                {
                    Point currentLocation = Mouse.GetPosition(this);
    
                    // 我们想绕着旋钮的中心旋转,而不是顶角
                    Point knobCenter = new Point(this.ActualHeight / 2, this.ActualWidth / 2);
    
                    // 计算角度
                    double radians = Math.Atan((currentLocation.Y - knobCenter.Y) /
                                               (currentLocation.X - knobCenter.X));
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = radians * 180 / Math.PI;
    
                    // 当X为负时,应用180度偏移,这样我们可以旋转所有的方向,但是这个地方怎么看着效果不是那么好看
                    if (currentLocation.X - knobCenter.X < 0)
                    {
                        rt.Angle += 180;
                    }
                    c.RenderTransform = rt;    
                }
            }
            /// <summary>
            /// 四周thumb的样式
            /// </summary>
            /// <param name="back"></param>
            /// <returns></returns>
            FrameworkElementFactory GetFactory(Brush back)
            {
                var fef = new FrameworkElementFactory(typeof(Ellipse));
                fef.SetValue(Ellipse.FillProperty, back);
                fef.SetValue(Ellipse.StrokeProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")));
                fef.SetValue(Ellipse.StrokeThicknessProperty, (double)2);
                return fef;
            }
        }
    }
    
    

    3.查找控件的方法

    由于在控件模板里有些控件的Name可能无法用Binding来绑定的,所以为了后面查找控件方便采用了UID来做为标识

             /// <summary>
            /// 通过UID查找某类型的子控件
            /// </summary>
            /// <example>StackPanel sp = GetChildObject<StackPanel>(this.LayoutRoot, "spDemoPanel")</example>
            /// <typeparam name="T">子控件类型</typeparam>
            /// <param name="obj">父控件</param>
            /// <param name="name">子控件名称,默认为空</param>
            /// <returns></returns>
            public static T GetChildObjectByUid<T>(DependencyObject obj, string uid = null) where T : FrameworkElement
            {
                DependencyObject child = null;
                T grandChild = null;
    
                for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
                {
                    child = VisualTreeHelper.GetChild(obj, i);
    
                    if (child is T && (((T)child).Uid == uid | string.IsNullOrEmpty(uid)))
                    {
                        return (T)child;
                    }
                    else
                    {
                        grandChild = GetChildObjectByUid<T>(child, uid);
                        if (grandChild != null)
                            return grandChild;
                     }
                }
                return null;
            }
            /// <summary>
            /// 通过名称查找某类型的子控件
            /// </summary>
            /// <example>StackPanel sp = GetChildObject<StackPanel>(this.LayoutRoot, "spDemoPanel")</example>
            /// <typeparam name="T">子控件类型</typeparam>
            /// <param name="obj">父控件</param>
            /// <param name="name">子控件名称,默认为空</param>
            /// <returns></returns>
            public static T GetChildObject<T>(DependencyObject obj, string name = null) where T : FrameworkElement
            {
                DependencyObject child = null;
                T grandChild = null;
    
                for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
                {
                    child = VisualTreeHelper.GetChild(obj, i);
    
                    if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
                    {
                        return (T)child;
                    }
                    else
                    {
                        grandChild = GetChildObject<T>(child, name);
                        if (grandChild != null)
                            return grandChild;
                    }
                }
                return null;
            }
    

    4.MVVM向ViewModel传递多个参数的类

    using System;
    using System.Linq;
    using System.Windows.Data;
    namespace WPF_Common
    {
        /// <summary>
        /// CommandParameter 多参数传递
        /// </summary>
        public class ObjectConvert : IMultiValueConverter
        {
            #region IMultiValueConverter Members
            public static object ConverterObject;
            public object Convert(object[] values, Type targetType,
              object parameter, System.Globalization.CultureInfo culture)
            {
                ConverterObject = values;
                string str = values.GetType().ToString();
                return values.ToArray();
            }
            public object[] ConvertBack(object value, Type[] targetTypes,
              object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
            #endregion
        }
    }
    

    二、为标识方向的控件

    1.XAML代码

    在这里面的ID_Head是用来标识方向的,最后我们可以获它的相对坐标就可以了。

    <UserControl x:Class="BlankApp2.Views.ArrowControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:BlankApp2.Views"
                 mc:Ignorable="d" 
                 d:DesignHeight="50" d:DesignWidth="100">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="2"/>
            </Grid.ColumnDefinitions>
            <Path  Grid.Column="0" Fill="Red" Panel.ZIndex="0" Data="M -15,8 L 17,17 C 17,17 19,18 17,19 L 17,19 L -15,28 C -15,28 -17,28.2 -16,26 L -16,26 L -5,18 L -16,10 C -16,10 -17,8.5 -15,8 Z" Margin="0,0,0,0" Stretch="Fill"/>
            <Ellipse Grid.Column="1" Name="ID_Head"   Height="1" Width="1" Stroke="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
               </Grid>
    </UserControl>
    

    2.CS代码

    这里为了方便就没用MVVM

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Shapes;
    namespace BlankApp2.Views
    {
        /// <summary>
        /// UserControl.xaml 的交互逻辑
        /// </summary>
        public partial class ArrowControl : UserControl
        {
            public ArrowControl()
            {
                InitializeComponent();
            }
            #region ID
            /// <summary>
            /// 左面标题
            /// </summary>
            public string ID
            {
                get => (string)GetValue(IDProperty);
                set => SetValue(IDProperty, value);
            }
            public static readonly DependencyProperty IDProperty =
                      DependencyProperty.RegisterAttached(
                            "ID",
                            typeof(string),
                            typeof(ArrowControl),
                            new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnPropertyChanged)));
    
            private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var b = d as ArrowControl;
                if (b != null && IDProperty != null)
                {
                  // b.Title;
                }
            }
            #endregion
            public Ellipse Direction 
            {
                get { return this.ID_Head; }
            }
            public static readonly DependencyProperty DirectionProperty =
                 DependencyProperty.RegisterAttached(
                       "Direction",
                       typeof(string),
                       typeof(ArrowControl),
                       new FrameworkPropertyMetadata("", null));
        }
    }
    

    三、主程序

    1.AXML代码

    在界面上主要用了两个ItemsControl 分别用来动态加载“线头”和“方框” 要注意的事,这两个ItemsControl是叠加在一起的,这样是为了让用户感觉在同一区域操作。但是叠加后会有一个控件遮挡的问题(鼠标是点击不到下面的控件的)。为了解决这个问题需要为最上层的控件背景设置为: Background=“{x:Null}” 并且 把穿透设置为: IsHitTestVisible=“True” 。

    <UserControl xmlns:Views="clr-namespace:BlankApp2.Views"  x:Class="BlankApp2.Views.PrismUserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:prism="http://prismlibrary.com/"            
               xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
            xmlns:local1="clr-namespace:WPF_Common;assembly=WPF_Common"
                 prism:ViewModelLocator.AutoWireViewModel="True" Background="Bisque">
        <UserControl.Resources>
            <ResourceDictionary>
                <!--多参数的初始化-->
                <local1:ObjectConvert x:Key="objectConverter"/>
            </ResourceDictionary>
        </UserControl.Resources>
        <Grid Background="Gainsboro" AllowDrop="True"   >
            <Grid.RowDefinitions>
                <RowDefinition Height="200*"/>
                <RowDefinition Height="50*"/>
            </Grid.RowDefinitions>
            <!--鼠标点击穿透:背景设置为: Background="{x:Null}" 并且 把穿透设置为: IsHitTestVisible="True"-->
            <ItemsControl x:Name="ic"  Background="{x:Null}" ItemsSource="{Binding objSource}"   Grid.Column="0" Grid.Row="0"  IsHitTestVisible="True"  >
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="{x:Type ContentPresenter}">
                        <Setter Property="Canvas.Left" Value="{Binding CnvLeft}"/>
                        <Setter Property="Canvas.Top" Value="{Binding CnvTop}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemTemplate >
                    <DataTemplate >
                        <Thumb IsHitTestVisible="True"   Name="Thumbs" Uid="{Binding Name}" Tag="{Binding Name}" Background="Black"  VerticalAlignment="Center" HorizontalAlignment="Center"  TextElement.FontStyle="Normal" >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="DragDelta">
                                    <i:InvokeCommandAction Command="{Binding onDragDeltaCommand}"   PassEventArgsToCommand="True"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                            <Thumb.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Header="删除" Name="miClickMe"     >
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Click">
                                                <i:InvokeCommandAction Command="{Binding onThumbDeleteCommand}"   PassEventArgsToCommand="True"/>
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </MenuItem>
                                </ContextMenu>
                            </Thumb.ContextMenu>
                            <Thumb.Template>
                                <ControlTemplate  >
                                    <!--将旋转的点改为中心RenderTransformOrigin = "0.5,0.5"-->
                                    <Grid Name="wpl" IsHitTestVisible="True"  HorizontalAlignment="Center"
                                         VerticalAlignment="Center"  Tag="{Binding ID}" RenderTransformOrigin = "0.5,0.5"   Background="Transparent" Height="80"  Width="80" >
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Loaded">
                                                <i:InvokeCommandAction Command="{Binding onThumbLoadedCommand}"    PassEventArgsToCommand="True"/>
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                        <!--将样式做成线头-->
                                        <Views:ArrowControl ID="{Binding ID}" x:Name="Arrow" Width="100" Height="50" />
                                        <Border Height="{Binding ElementName=wpl,Path=Height}" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="6" Background="LightYellow" BorderThickness="1" Panel.ZIndex="1">
                                            <Grid Background="Black">
                                                <!--为线两端加上两个圆用于获取线的两端坐标-->
                                                <Ellipse Name="LineTop"   Height="10" Width="10" Stroke="White" Fill="White" VerticalAlignment="Top" HorizontalAlignment="Center" />
                                                <Ellipse Name="LineBottom"   Height="10" Width="10" Stroke="Gold" Fill="Gold" VerticalAlignment="Bottom" HorizontalAlignment="Center" />
                                            </Grid>
                                        </Border>
                                    </Grid>
                                </ControlTemplate>
                            </Thumb.Template>
                        </Thumb>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid Name="myG"  Grid.Column="0" Grid.Row="0"  IsHitTestVisible="True"  Background="Blue">                      
                        </Grid>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
            <ItemsControl x:Name="ic2" ItemsSource="{Binding objSource2}" Background="{x:Null}"  Grid.Column="0" Grid.Row="0" Panel.ZIndex="1"  IsHitTestVisible="True" >
                            <ItemsControl.ItemTemplate >
                    <DataTemplate >
                        <Thumb IsHitTestVisible="True" Name="Thumbs" Tag="{Binding Name}" Background="Black"  VerticalAlignment="Center" HorizontalAlignment="Center"  TextElement.FontStyle="Normal" >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="DragDelta">
                                    <i:InvokeCommandAction Command="{Binding onDragDeltaCommand}"   PassEventArgsToCommand="True"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                            <Thumb.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Header="删除" Name="miClickMe"     >
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Click">
                                                <i:InvokeCommandAction Command="{Binding onThumbDeleteCommand}"   PassEventArgsToCommand="True"/>
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </MenuItem>
                                </ContextMenu>
                            </Thumb.ContextMenu>
                            <Thumb.Template>
                                <ControlTemplate >
                                    <!--将旋转的点改为中心RenderTransformOrigin = "0.5,0.5"-->
                                    <Grid Name="wpl"   HorizontalAlignment="Center" 
                                         VerticalAlignment="Center"  Tag="{Binding ID}" RenderTransformOrigin = "0.5,0.5"   Background="Transparent" Height="80"  Width="80" >
                                        <i:Interaction.Triggers>
                                            <!--控件加载后调用事件-->
                                            <i:EventTrigger EventName="Loaded">
                                                <i:InvokeCommandAction Command="{Binding onThumbLoadedCommand}"    PassEventArgsToCommand="True"/>
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                        <!--将样式改成一个方框-->
                                        <Rectangle x:Name="rl" StrokeThickness="2" Stroke="Red" Fill="AliceBlue" Opacity="0.5"/>
                                    </Grid>
                                </ControlTemplate>
                            </Thumb.Template>
                        </Thumb>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate  >
                        <Grid Name="myG2"  Grid.Column="0" Grid.Row="0"  Background="{x:Null}" IsHitTestVisible="True" >
                            <!--<Grid.Background>
                                <ImageBrush Stretch="None" 
                            ImageSource="{Binding ImageSources}" 
                            AlignmentY="Center" 
                            AlignmentX="Center">
                                </ImageBrush>
                            </Grid.Background>-->
                        </Grid>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
            <Button Content="线头" HorizontalAlignment="Left" Margin="88,34,0,0" Grid.Row="1" VerticalAlignment="Top" Command="{Binding AddT}"/>
            <Button Content="方框" HorizontalAlignment="Left" Margin="138,34,0,0" Grid.Row="1" VerticalAlignment="Top" Command="{Binding AddT2}"/>
            <Button Content="Get" HorizontalAlignment="Left" Margin="50,34,0,0" Grid.Row="1" VerticalAlignment="Top" Command="{Binding GetT}"  >
                <Button.CommandParameter>
                    <MultiBinding Converter="{ StaticResource ResourceKey=objectConverter}">
                        <Binding ElementName="ic"></Binding>
                        <Binding ElementName="rtl"></Binding>
                    </MultiBinding>
                </Button.CommandParameter>
            </Button>
            <TextBlock Grid.Row="1" Margin="200,34,0,0" Text="{Binding MarginValue}"/>
        </Grid>
    </UserControl>
    

    2.ViewModel端的CS代码

    using Prism.Commands;
    using Prism.Ioc;
    using Prism.Modularity;
    using Prism.Mvvm;
    using Prism.Regions;
    using System;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Documents;
    using WPF_Common;
    namespace BlankApp2.ViewModels
    {
        public class PrismUserControl1ViewModel : BindableBase, IModule
        {
            /// <summary>
            /// 拖动事件
            /// </summary>
            public DelegateCommand<object> onDragDeltaCommand { get; private set; }
            /// <summary>
            /// 控件加载后事件
            /// </summary>
            public DelegateCommand<object> onThumbLoadedCommand { get; private set; }
            /// <summary>
            /// 控件删除事件
            /// </summary>
            public DelegateCommand<object> onThumbDeleteCommand { get; private set; }
            /// <summary>
            /// 获取坐标事件
            /// </summary>
            public DelegateCommand<object> GetT { get; private set; }
            /// <summary>
            /// 添加线头事件
            /// </summary>
            public DelegateCommand AddT { get; private set; }
            /// <summary>
            /// 添加方框事件
            /// </summary>
            public DelegateCommand AddT2 { get; private set; }
            /// <summary>
            /// 加载本页面事件
            /// </summary>
            public PrismUserControl1ViewModel()
            {
                onDragDeltaCommand = new DelegateCommand<object>(onDragDelta);
                onThumbLoadedCommand = new DelegateCommand<object>(onThumbLoaded);
                onThumbDeleteCommand = new DelegateCommand<object>(onThumbDelete);
                AddT = new DelegateCommand(Add);
                AddT2 = new DelegateCommand(Add2);
                GetT = new DelegateCommand<object>(GetTOne);
            }
            /// <summary>
            /// 获取坐标事件
            /// </summary>
            /// <param name="obj"></param>
            private void GetTOne(object obj)
            {
                ///obj对像是View端传来的多参数
                object[] multiObj = obj as object[];
                Grid grid = FindChildControlHelper.GetChildObject<Grid>(multiObj[0] as DependencyObject, "myG");
                //Grid wplGrid = FindChildControlHelper.GetChildObject<Grid>(multiObj[0] as DependencyObject, "wpl");
                //Ellipse eps = FindChildControlHelper.GetChildObject<Ellipse>(multiObj[0] as DependencyObject , "ID_Head");
                //Ellipse LineTop = FindChildControlHelper.GetChildObject<Ellipse>(multiObj[0] as DependencyObject, "LineTop");
                //Ellipse LineBottom = FindChildControlHelper.GetChildObject<Ellipse>(multiObj[0] as DependencyObject, "LineBottom");
                //Rectangle obj1 = FindChildControlHelper.GetChildObject<Rectangle>(multiObj[0] as DependencyObject, "rtl");
                //System.Windows.Point pointeps = eps.TranslatePoint(new System.Windows.Point(), grid);
                //System.Windows.Point pointLineTop = LineTop.TranslatePoint(new System.Windows.Point(), grid);
                //System.Windows.Point pointLineBottom = LineBottom.TranslatePoint(new System.Windows.Point(), grid);
    
                for (int i = 0; i < objSource.Count; i++)
                {
                    string sourceName = objSource[i].Name;
                    Thumb Thumb1 = FindChildControlHelper.GetChildObjectByUid<Thumb>(multiObj[0] as DependencyObject, sourceName);
                    Grid wplGrid = FindChildControlHelper.GetChildObject<Grid>(Thumb1 as DependencyObject, "wpl");
                    System.Windows.Point point = Thumb1.TranslatePoint(new System.Windows.Point(), grid);//获取控件在grid的相对坐标
                    MessageBox.Show(Thumb1.Name + ";" + Thumb1.Tag + "H:" + Thumb1.Height + ";" + "W:" + Thumb1.Width + "T:" + Thumb1.Margin.Top + ";" + "L:" + Thumb1.Margin.Left);
                }
            }
            private string _MarginValue;
            /// <summary>
            /// Margin四个方向的值
            /// </summary>
            public string MarginValue
            {
                get { return _MarginValue; }
                set { SetProperty(ref _MarginValue, value); }
            }
            private int _CanvasWidth = 600;
            public int CanvasWidth
            {
                get { return _CanvasWidth; }
                set { SetProperty(ref _CanvasWidth, value); }
            }
            private int _CanvasHeight = 700;
            public int CanvasHeight
            {
                get { return _CanvasHeight; }
                set { SetProperty(ref _CanvasHeight, value); }
            }
            /// <summary>
            /// 添加线头
            /// </summary>
            private void Add()
            {
                for (int i = 1; i < 2; i++)
                {
                    int k = objSource.Count + 1;
                    ObjEntity obj = new ObjEntity();
                    obj.ID = k;
                    obj.Name = "Name" + k;
                    obj.onDragDeltaCommand = onDragDeltaCommand;
                    obj.onThumbLoadedCommand = onThumbLoadedCommand;
                    objSource.Add(obj);
                }
            }
            /// <summary>
            /// 添加方框
            /// </summary>
            private void Add2()
            {
                for (int i = 1; i < 2; i++)
                {
                    int k = objSource.Count + 1;
                    ObjEntity obj = new ObjEntity();
                    obj.ID = k;
                    obj.Name = "NameL" + k;
                    obj.onDragDeltaCommand = onDragDeltaCommand;
                    obj.onThumbLoadedCommand = onThumbLoadedCommand;
                    objSource2.Add(obj);
                }
            }
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="obj"></param>
            /// <exception cref="NotImplementedException"></exception>
            private void onThumbDelete(object obj)
            {
                objSource.Remove(obj as ObjEntity);
            }
            /// <summary>
            /// 加载四周的Thumb
            /// </summary>
            /// <param name="obj"></param>
            private void onThumbLoaded(object obj)
            {
                if (obj is System.Windows.RoutedEventArgs e)
                {
                    AdornerLayer layer = AdornerLayer.GetAdornerLayer((Grid)e.Source);
                    layer.Add(new GridAdorner((Grid)e.Source));
                }
            }
            /// <summary>
            /// 拖动逻辑
            /// </summary>
            /// <param name="obj"></param>
            private void onDragDelta(object obj)
            {
                if (obj is DragDeltaEventArgs e)
                {
                    if (((System.Windows.FrameworkElement)e.Source).DataContext is ObjEntity t)
                    {
                        var m = ((System.Windows.FrameworkElement)e.Source).Margin;
                        MarginValue = $"; m.Left={m.Left} + e.HorizontalChange={e.HorizontalChange} ;;m.Top={m.Top} +  e.VerticalChange={e.VerticalChange};;  m.Right={m.Right};;m.Bottom={m.Bottom}";
                        ((System.Windows.FrameworkElement)e.Source).Margin = new Thickness(m.Left + e.HorizontalChange, m.Top + e.VerticalChange, m.Right, m.Bottom);
                    }
                }
            }
            /// <summary>
            /// 线头
            /// </summary>
            private ObservableCollection<ObjEntity> _objSource = new ObservableCollection<ObjEntity>();
            public ObservableCollection<ObjEntity> objSource
            {
                get { return _objSource; }
                set { SetProperty(ref _objSource, value); }
            }
            /// <summary>
            /// 方框
            /// </summary>
            private ObservableCollection<ObjEntity> _objSource2 = new ObservableCollection<ObjEntity>();
            public ObservableCollection<ObjEntity> objSource2
            {
                get { return _objSource2; }
                set { SetProperty(ref _objSource2, value); }
            }
            public void OnInitialized(IContainerProvider containerProvider)
            {
                var regionManager = containerProvider.Resolve<IRegionManager>();
                regionManager.RegisterViewWithRegion("ContentRegion", typeof(Views.PrismUserControl1));
            }
            public void RegisterTypes(IContainerRegistry containerRegistry)
            {
                // throw new NotImplementedException();
            }
        }
    }
    

    总结

    本文功能只是一个很简陋的Demo希望对大家有帮助。发辉你们的想想去拓展它吧。
    源码下载

    展开全文
  • WPF MVVM无Command属性的控件绑定事件

    热门讨论 2014-07-03 22:16:35
    我们在WPF开发中应用MVVM开发模式时,一般用来绑定Button 的Command命令,但是有很多控件MS没有给出Command命令,我们需要添加一个DLL来增加绑定时的属性。
  • WPF动态创建控件,并给最后创建控件加入事件
  • 密码框控件是一种特殊类型的 TextBox,旨在输入密码。键入的字符将替换为星号。由于密码框包含合理的密码,因此不允许剪切,复制,撤消和重做命令
  • WPFMVVM模式中GridControl控件数据绑定 MVVM模式,DevExpress v20.2的dxg:GridControl控件 在xaml绑定数据源: View <dxg:GridControl Grid.Column=“0” ItemsSource="{Binding Persons}"> dxg:...
  • 使用wpf开发有时需要动态加载控件,直接再后台写cs代码,对于样式会很难写而且可读性会比较差,这个时候我们就需要想办法完全在xaml中定义动态加载控件的样式,虽然我们可以定义模板放在资源字典中,然后在后台获取...
  • WPF MVVM--数据绑定

    2022-04-28 09:19:07
    WPF MVVM--数据绑定 一、数据绑定要达到的效果 数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上。从界面反映到绑定的数据源是很...
  • WPF MVVM--事件绑定

    2022-04-20 09:15:08
    WPF MVVM--事件绑定 事件转命令 在我们大多数拥有Command依赖属性的控件,大多数是由于继承了ICommandSource接口,ICommandSource接口拥有三个函数成员,ICommand接口类型属性Command,object 类型属性...
  • 使用ItemsControl和布局控件配合
  • MVVM WPF 绑定颜色

    千次阅读 2020-07-16 17:38:32
    这样即可绑定 但是需要注意的是这里的Color是System.Windows.Media.Color不是Drawing.Color 也可以直接Background绑定,但是需要进行一个convert public class Matrix2Len : IValueConverter { object ...
  • 绑定代码: Command="{Binding DataContext.ModifyCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}" ModifyCommand:绑定的命令名称 FindAncestor:寻找父级控件 AncestorType:...
  • WPF DataGrid MVVM模式数据绑定

    千次阅读 2020-12-11 17:48:51
    WPF DataGrid MVVM模式数据绑定 1、创建Model public class User { public int Id { get; set; } public string Name { get; set; } public char Sex { get; set; } public int Age { get; set; } public ...
  • WPF_ComboBox的MVVM绑定(一)

    千次阅读 2020-10-13 19:57:23
    WPF_ComboBox的MVVM绑定 一、背景 在控件ComboBox中,我们一般会将选择项写在ComboBoxItem中,例如: <ComboBox> <ComboBoxItem Content="Item0" /> <ComboBoxItem Content="Item1" /> <...
  • 20、wpfMVVM命令绑定

    2022-06-24 10:22:20
    Command可以有效降低前后端的耦合,有利于代码的管理和可读性。前端控件的Command有时可能...但是借助事件转Command实现MVVM模式的控件,就需要通过Command将EventArgs中相关信息传给ViewModel去解析操作。.........
  • WPF MVVM 属性绑定

    2021-05-08 17:59:07
    WPF MVVM 关于绑定 WPF里面用mvvm框架,对于想改变一个控件的属性来说,没有以前直接在cs后台类里面直接获取到这个控件的name然后就可以改变这个属性这么方便了。Mvvm在这里不可以直接通过控件的name来控制这个控件...
  • MVVMLight 4:绑定绑定的各种使用场景
  • 最近研究WPF,遇到并解决了一些难题(至少是初学者的入门难题),包括: 1)控件如何绑定数据? 2)控件与数据如何双向绑定? 3)控件如何绑定类成员变量? 4)控件如何绑定类对象的成员变量? 5)每次加载页面...
  • C# WPF MVVM 实战 – 5- 用绑定,通过 VM 设置 View 的控件焦点
  • MVVM模式解析和在WPF中的实现(二)数据绑定系列目录:0x00 数据绑定要达到的效果数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上。...
  • 这个Demo是WPFMVVM模式的一个登录窗口的完整实例,包含了在MVVM模式下的数据绑定、命令和事件、PasswordBox的绑定、RadioButton等一对多控件绑定、关闭窗口和打开新窗口和数据验证等内容。
  • 公司的需求,看了看之前的代码,同一个控件在好几个地方用到了,现在需求要求不同界面显示不同的数据,只需要在MVVM绑定的时候增加自定义属性即可。 首先在控件的xaml.cs代码中增加属性 然后调试生成解决方案,再在...
  • WpfMVVM之Visibility 属性绑定

    千次阅读 2020-06-23 14:49:18
    小伙伴们在Wpf中使用MVVM设计时,控件的Visibility 属性如何绑定呢? 二、思路 不需要对Visibility 进行值转换器,直接按照普通属性方式绑定即可。 XMAL代码 <GroupBox Header="groupBox" Visibility="{Binding ...
  • ComboBox是一个非常常用的界面控件,它的数据源ItemsSource既可以绑定一个List列表,也可以是一个字典,本篇文章就讲这些内容展开讲解。 01 — 前言 ComboBox是一个非常常用的下拉菜单界面控件,它的数据源...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,897
精华内容 1,558
热门标签
关键字:

MVVM WPF 动态添加控件及绑定