欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF 自定义控件操作自定义控件

程序员文章站 2022-01-05 10:50:25
...

  场景:一个信息窗体,用Grid分成两列,左边的是信息列表自定义控件,右边的是信息内容自定义控件(高度未占满整列),当点击信息列表中的某一条信息时,信息内容控件的位置要与列表中所选中的那条信息对齐。

  以下为DEMO代码:

  MainWindows.xaml:     

<Window x:Class="NotifyProperty.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Msg="clr-namespace:NotifyProperty"
        x:Name="mainWin" 
        Title="MainWindow" Height="600" Width="800">
    <Grid x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <!--信息列表-->
        <Msg:MessageList x:Name="MsgList" Grid.Column="0"/>
        
        <!--信息内容-->
        <Msg:MsgInfo x:Name="msgInfo" Grid.Column="1" Width="300" Height="200" Margin="20,20,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>

        <TextBlock Text="{Binding ElementName=mainWin, Path=MarginTop}" Margin="20,20,0,0" Grid.ColumnSpan="2" Grid.Column="1" />
    </Grid>
</Window>

 

MainWindows.xaml.cs:   

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.ComponentModel;

namespace NotifyProperty
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public Double MarginTop
        {
            get { return (Double)GetValue(MarginTopProperty); }
            set { SetValue(MarginTopProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MarginTop.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MarginTopProperty =
            DependencyProperty.Register("MarginTop", typeof(Double), typeof(MainWindow));

        DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(MarginTopProperty, typeof(MainWindow));
        

        public MainWindow()
        {
            InitializeComponent();

            //属性绑定
            Binding binding = new Binding();
            binding.Source = MsgList;
            binding.Path = new PropertyPath("MarginTop");
            BindingOperations.SetBinding(this, MarginTopProperty, binding);

            //附加属性监听
            dpd.AddValueChanged(this, OnMyDependencyPropertyChanged); 
        }


        /// <summary>
        /// 附加属性监听事件
        /// 计算MsgInfo对象的Margin-Top
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnMyDependencyPropertyChanged(object sender, EventArgs e)
        {
            double mLeft = 20;
            double mTop = 0;

            double parentHeight = grid.ActualHeight-20;

            if (MarginTop + msgInfo.Height > parentHeight)
            {
                mTop = parentHeight - msgInfo.Height;
            }
            else
            {
                mTop = MarginTop;

                if (mTop < 20)
                {
                    mTop = 20;
                }
            }

            msgInfo.Margin = new Thickness(mLeft, mTop, 0, 0);
            
        }
    }
}

 

  MessageList.xaml:  

<UserControl x:Class="NotifyProperty.MessageList"
             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="300" d:DesignWidth="300">
    <Grid x:Name="grid">
        <ListBox x:Name="lvStudent" ItemsSource="{Binding}" Width="{Binding ElementName=grid, Path=ActualWidth}" MouseLeftButtonUp="lvStudent_MouseLeftButtonUp" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Blue" BorderThickness="1" Margin="5" Width="300" Height="80">
                        <TextBlock Text="{Binding Age}" FontSize="26"/>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

 

  MessageList.xaml.cs

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.ComponentModel;
using System.Diagnostics;

namespace NotifyProperty
{
    /// <summary>
    /// MessageList.xaml 的交互逻辑
    /// </summary>
    public partial class MessageList : UserControl, INotifyPropertyChanged
    {
        private double marginTop;

        public double MarginTop
        {
            get { return marginTop; }
            set 
            { 
                marginTop = value;
                RaisePropertyChanged("MarginTop");
            }
        }

        public MessageList()
        {
            InitializeComponent();

            List<Student> stuList = new List<Student>();

            for (int i = 0; i < 10; i++)
            {
                Student stu = new Student();
                stu.Age = i;
                stuList.Add(stu);
            }

            this.lvStudent.ItemsSource = stuList;
        }

        /// <summary>
        /// 列表点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvStudent_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            ListBoxItem lbi = null;
            if (lvStudent.Items.Count > 0 && lvStudent.SelectedIndex != -1)
            {
                lbi = lvStudent.ItemContainerGenerator.ContainerFromIndex(lvStudent.SelectedIndex) as ListBoxItem;
            }
            
            Point point = e.MouseDevice.GetPosition(this);

            if (lbi != null)
            {
                MarginTop = point.Y - e.MouseDevice.GetPosition(lbi).Y;// +lbi.ActualHeight / 2;
            }
            else
            {
                MarginTop = point.Y;
            }
        }     

        #region Notify Method
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName)
        {
            this.VerifyPropertyName(propertyName);

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        #region 属性名验证
        protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
        [Conditional("DEBUG")]
        [DebuggerStepThrough]
        public void VerifyPropertyName(string propertyName)
        {
            // If you raise PropertyChanged and do not specify a property name,
            // all properties on the object are considered to be changed by the binding system.
            if (String.IsNullOrEmpty(propertyName))
                return;

            // Verify that the property name matches a real,  
            // public, instance property on this object.
            if (TypeDescriptor.GetProperties(this)[propertyName] == null)
            {
                string msg = "Invalid property name: " + propertyName;

                if (this.ThrowOnInvalidPropertyName)
                    throw new ArgumentException(msg);
                else
                    Debug.Fail(msg);
            }
        }
        #endregion

        #endregion

    }

    public class Student
    {
        public int Age { get; set; }
    }
}

 

  MsgInfo.xaml:  

<UserControl x:Class="NotifyProperty.MsgInfo"
             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="600" d:DesignWidth="800">
    <Border BorderBrush="Red" BorderThickness="2"/>
</UserControl>

 

  MsgInfo.xaml.cs: ~Nothing~~

 

  以上为简单实现的代码,接触WPF不久,不足的地方,还望高手们指正~~

 

 

转载于:https://www.cnblogs.com/Dincat/archive/2012/07/08/2581735.html