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


      场景:一个信息窗体,用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不久,不足的地方,还望高手们指正~~

  • 相关阅读:
    DBC的故事
    MDF,了解一下
    PAT A 1059 Prime Factors (25分)
    素数的判断与素数表的获取
    PAT A 1014 Waiting in Line (30分)
    n皇后问题(全排列+回溯)
    最长回文子串(c++)
    传输方式的分类
    OSI模型概述
    进制转换
  • 原文地址:https://www.cnblogs.com/Dincat/p/2581735.html
Copyright © 2020-2023  润新知