【问题标题】:Creating _MouseLeftButtonDown for dynamically created rectangles in WPF在 WPF 中为动态创建的矩形创建 _MouseLeftButtonDown
【发布时间】:2014-03-12 17:36:47
【问题描述】:

我的应用程序显示了办公楼层的布局,其中座位被描绘为一个矩形,并且每个座位 ID 的边距、笔划、高度、宽度和对齐方式都保存在数据库中。根据分配状态,矩形的填充为红色或绿色。分配状态和占用详细信息保存在 SQL 数据库中。我需要为每个矩形设置单独的 MouseLeftButtonDown 方法。这将向我显示居住者的详细信息。

//Code Behind
public SeatUserControl()
        {
         string cubeId = "";
         string status = "";
         string name = "";
         string number = "";
         int height = 0;
         int width = 0;
         int leftMargin = 0;
         int topMargin = 0;
            InitializeComponent(); 
            SqlDataAdapter data = new SqlDataAdapter();
            DataTable dt = new DataTable();
            string SqlQuery = "select c.SeatId,c.Height,c.Width,c.Stroke,c.MarginTop,c.MarginLeft,e.Status,e.EmpName,e.EmpNumber from SeatDetails c Join MasterData e ON c.SeatId =e.SeatId";
            SqlConnection sqlconn = new SqlConnection(connectionstring);
            sqlconn.Open();
            data = new SqlDataAdapter(SqlQuery, sqlconn);
            data.Fill(dt);
            try
            {
                foreach (DataRow row in dt.Rows)
                {
                    leftMargin = int.Parse(row["MarginLeft"].ToString());
                    topMargin = int.Parse(row["MarginTop"].ToString());
                    height = int.Parse(row["Height"].ToString());
                    width = int.Parse(row["width"].ToString());
                    status = row["Status"].ToString();
                    cubeId = row["SeatId"].ToString();
                    name = row["EmpName"].ToString();
                    number = row["EmpNumber"].ToString();
                    PlaceRectangles();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            sqlconn.Close();
        }
        public string PlaceRectangles()
        {
            Rectangle rect = new Rectangle();
            rect.Height = height;
            rect.Width = width;
            SolidColorBrush StrokeBrush = new SolidColorBrush(Colors.Black);
            rect.Stroke = StrokeBrush;
            rect.VerticalAlignment = VerticalAlignment.Top;
            rect.HorizontalAlignment = HorizontalAlignment.Left;
            rect.Margin = new Thickness(leftMargin, topMargin, 0, 0);
            rect.RadiusX = 8;
            rect.RadiusY = 5;
           if (status.Equals("Allocated"))
            {
                SolidColorBrush myBrush = new SolidColorBrush(Colors.RoyalBlue);
                rect.Fill = myBrush;
            }
           else if (status.Equals("Available"))
            {
                SolidColorBrush myBrush = new SolidColorBrush(Colors.Red);
                rect.Fill = myBrush;
            }
           else 
            {
                SolidColorBrush myBrush = new SolidColorBrush(Colors.White);
                rect.Fill = myBrush;
            }
            seatCanvas.Children.Add(rect);
     }
}

//XAML
<UserControl x:Class="SpaceAllocator.SeatUserControl"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="580" d:DesignWidth="800">
    <Grid Height="580" Width="800">
        <Canvas Name="seatCanvas" Height="580" Width="800" Margin="0,3,-2,78">       </Canvas>
    </Grid>
</UserControl>
enter code here

【问题讨论】:

  • 强烈建议您使用正确的 DataBinding 和正确的 ItemsControl 和正确的 DataTemplates,而不是在 WPF 中的过程代码中创建和操作 UI 元素。由于可视化树的复杂性而存在问题,因此不鼓励这种方法,并且由于它的程序性质而繁琐,通常需要更多代码并且不如声明性的基于 DataBinding 的方法那么优雅。发布您当前的代码和 XAML,我可以告诉您在 WPF 中执行所需操作的正确方法。
  • 嗨,@HighCore 我已经包含了后面的代码和我的应用程序中使用的 XAML。请提出更好的方法。
  • @HighCore,我们可以做得更好吗?
  • 我给你准备一个小样。

标签: c# wpf rectangles


【解决方案1】:

当你创建一个矩形时添加一个事件处理程序:

System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle();
rect.MouseLeftButtonDown += rect_MouseLeftButtonDown;
// apply margins and what not

然后你在这里处理鼠标左键:

void rect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
      var rect = sender as System.Windows.Shapes.Rectangle;
      // do whatever
}

【讨论】:

    【解决方案2】:

    如果您在应用程序启动时调用此代码,则会自动将事件处理程序添加到所有 Rectangle 类型的新对象:

    EventManager.RegisterClassHandler(typeof(Rectangle), MouseLeftButtonDownEvent, 
        new MouseButtonEventHandler(OnMouseDown), false);
    
    private void OnMouseDown(object sender, MouseButtonEventArgs e)
    {
    }
    

    【讨论】:

    • 嗨@Flat 我收到以下错误:- “指定的视觉对象已经是另一个视觉对象的子对象或 CompositionTarget 的根”。在我看来,classHandler 是为第一个生成的矩形注册的,在第二个循环中它抛出了这个异常。我的要求是获得与矩形数量一样多的处理程序(基于数据库中的数据)。请提出建议。
    • 函数“RegisterClassHandler”将此处理程序添加到所有矩形,而不仅仅是第一个。当您尝试将一个控件添加到多个父元素时,通常会发生您遇到的错误,例如,如果您调用 'seatCanvas.Children.Add(rect);'多次为同一个对象。
    • 我现在遇到了问题。它现在完美运行。 @Flat
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 2015-11-24
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多