• (WPF) 再议binding:点击User Control时,User Control变换颜色或做其他的处理。


    Binding 是前台UI(显示层)和后台代码(数据层)的桥梁。理论上当后台的数据变动时,显示的数据或样式应该随之而变。这些是动态的。

    对于Binding的设置可以在前台Xaml,也可以在后台Code里面定义,但是既然Xaml可以做很多事情,那么所有对UI的操作我们都可以交给它。

     其实,WPF的本身是一种数据驱动UI的设计模式,使用了MVVM(Model-View-ViewModel)的模式。

    以下是绑定的基本思路:

    目标(依赖对象(依赖属性))  <=====Binding =====> 源(CLR 对象(属性))

    实验1

    设计一个圆形的球,包括红球和篮球,有编号。初始状态为灰色,当选中时,红球颜色显示为红,篮球颜色显示为蓝。再次选中时,颜色返回为初始状态(灰色)

    另外,当球被选中时,可以处理一下数据,如读取编号。

    思路:

    1.首先设计一个Ball 类 包含了IsSelected, Type, Index 属性,并继承了INotifyPropertyChanged接口,当IsSelected属性变更的时候,产生了PropertyChanged的Event。

    2.创建了一个BallControl的 User Control (WPF). 

    3.bindingBall类到BallControl上。对binding做一些设定,从而实现实验1的需求。

    实现:

    1. 新建Ball类. 实现INotifyPropertyChanged 接口,当属性IsSelected值变化的时候,调用PropertyChanged event

        public class Ball : INotifyPropertyChanged
        {
            /// <summary>
            /// Fired whenever a property changes.  Required for
            /// INotifyPropertyChanged interface.
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool selected; 
    
            private BallType type;
    
            private int index;
    
            private Point size;
    
            public Ball()
                :this(false, BallType.gray, 0, new Point(40,40))
            {
            }
    
            public Ball(bool ballIsSelected, BallType ballType, int ballIndex, Point ballSize)
            {
                this.selected = ballIsSelected; 
                this.type = ballType; 
                this.index = ballIndex; 
                this.size = ballSize; 
            }
    
            public bool IsSelected
            {
                get
                {
                    return this.selected; 
                }
    
                set
                {
                    if (value != this.selected)
                    {
                        this.selected = value;
                        if (this.PropertyChanged != null)
                        {
                            this.PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
                        }
                    }
                }
            }
    
            public BallType Type
            {
                get
                {
                    return this.type;
                }
            }
    
            public int Index
            {
                get
                {
                    return this.index;
                }
            }
        }
    
        public enum BallType
        {
            gray,
    
            Red,
    
            Blue,
        }

    2. 新建一个User Control (WPF), 名为BallControl,依次放入Grid, Border, Ellipse, TextBlock 控件. 完成 UI 布局。

    在后台为鼠标点击动作添加一个Event,当Ball控件被点击选择的时候,会做一些需要的处理。 

    <UserControl x:Name="myBallControl"
                 x:Class="BallSelection.BallControl"
                 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:BallSelection"
                 mc:Ignorable="d"
                 Height="100"
                 Width="100">
        <Grid Height="100"
              Width="100"
              VerticalAlignment="Top"
              MouseDown="UIElement_OnMouseDown">
            <Border BorderBrush="Black"
                    BorderThickness="1"
                    HorizontalAlignment="Left"
                    Width="100"
                    Height="100"
                    RenderTransformOrigin="0.481,0.183">
                <Ellipse x:Name="circle"
                         Stroke="Black"
                         Margin="6,6,6,6">
                </Ellipse>
            </Border>
            <TextBlock x:Name="tbIndex"
                       Text="0"
                       FontSize="58"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center" />
        </Grid>
    </UserControl>
        /// <summary>
        /// Interaction logic for BallControl.xaml
        /// </summary>
        public partial class BallControl : UserControl
        {
            public event EventHandler<EventArgs> SelectionChanged;
    
            public BallControl()
            {
                InitializeComponent();
            }
    
            private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
            {
                if (this.SelectionChanged != null)
                {
                    this.SelectionChanged(this, EventArgs.Empty);
                }
            }    
        }

    4. 设计MainWindow的UI,依次放入Grid,WrapStack,和BallControl。

    <Window x:Class="BallSelection.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:BallSelection"
            Title="MainWindow"
            Height="350"
            Width="525">
        <Grid>
            <Grid HorizontalAlignment="Left"
                  Height="227"
                  Margin="51,38,0,0"
                  VerticalAlignment="Top"
                  Width="396">
                <WrapPanel x:Name="wpBalls"
                           HorizontalAlignment="Left"
                           Height="227"
                           VerticalAlignment="Top"
                           Width="386">
                    <local:BallControl x:Name="redBallControl" />
                    <local:BallControl x:Name="blueBallControl" />
                </WrapPanel>
            </Grid>
        </Grid>
    </Window>

    5. 进行Binding, 有两种方法:一种是在后台Code里面进行binding, 另外一种是在前台Xaml里面进行binding。

    方法一:在后台Code里面进行binding

     public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                this.InitializeBalls(); 
            }
    
            private void InitializeBalls()
            {
                Ball redBall = new Ball(false, BallType.Red, 1, new Point(50,50));
    
                Binding bindingIndex = new Binding()
                {
                    Source = redBall,
                    Path = new PropertyPath("Index")
                };
    
                // this is  equal to: this.blueBallControl.tbIndex.SetBinding(TextBlock.TextProperty, bindingIndex);
                BindingOperations.SetBinding(this.redBallControl.tbIndex, TextBlock.TextProperty, bindingIndex); 
    
                Binding bindingSelect = new Binding()
                {
                    Source = redBall,
                    Path = new PropertyPath("IsSelected"),
                    Converter = new BooleanToColor(),
                };
    
                BindingOperations.SetBinding(this.redBallControl.circle, Ellipse.FillProperty, bindingSelect);
    
                // Handle selection changed event. 
                this.redBallControl.SelectionChanged += ((s, e) =>
                {
                    redBall.IsSelected = !redBall.IsSelected;
                    MessageBox.Show(string.Format("BallControl Index {0} is selected.	
    . Ball Type:{1}, Index:{2}, IsSelected:{3}.", this.redBallControl.tbIndex.Text, redBall.Type.ToString(), redBall.Index, redBall.IsSelected));
                }); 
            }
    
        }

    这里在binding的过程中,当ball control被选中的时候, 颜色会自动进行转换,所以需要一个Converter。

        public class BooleanToColor : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (targetType != typeof(Brush))
                    throw new InvalidOperationException("The target must be a Brush");
    
                if (value == null)
                    return Brushes.Gray;
    
                return (bool)value ? Brushes.Red : Brushes.Gray;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }

    方法二:在前台Xaml里面进行binding

    (待续)

  • 相关阅读:
    git总是需要输入用户名密码问题解决
    安装Elasticsearch与Kibana汉化记录
    ubuntu下通过certbot自动化生成letsencrypt证书配置nginx服务器https记录
    ubuntu通过apt安装最新稳定版nginx记录
    linux磁盘管理与lvm琐事
    docker搭建常用环境记录
    线程池如何复用一个线程-- ThreadPoolExecutor的实现(未完)
    为什么切换线程比切换进程开销小
    Tomcat &servlet字符集编码问题
    字符和字符串在Java中的旅程
  • 原文地址:https://www.cnblogs.com/fdyang/p/3807941.html
Copyright © 2020-2023  润新知