首页 > 编程语言 >C# 自定义控件 UserControl 绑定

C# 自定义控件 UserControl 绑定

时间:2022-11-20 19:55:37浏览次数:42  
标签:控件 自定义 C# object System value Windows using public

主界面

<Window x:Class="MyWPFSimple2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyWPFSimple2"
        mc:Ignorable="d" WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="460" Width="500">
    
    <Window.DataContext>
        <local:VMMainWindow/>
    </Window.DataContext>
    <Window.Resources>
        <ResourceDictionary Source="PersonInfoDTmpl.xaml"/>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <GroupBox Header="绑定 DataContext">
                <local:PersonInfo/>
            </GroupBox>
            <Button x:Name="btnShow" Click="btnShow_Click" Content="显示信息" Margin="0 5 0 0"/>
            <GroupBox Header="散装">
                <StackPanel HorizontalAlignment="Center" Margin="5">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="姓名:" VerticalAlignment="Center"/>
                        <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center" Text="{Binding Name}"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="0 2 0 0">
                        <TextBlock Text="年龄:" VerticalAlignment="Center"/>
                        <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center" Text="{Binding Age}" />
                    </StackPanel>
                </StackPanel>
            </GroupBox>
            <GroupBox Header="数据模板" HorizontalAlignment="Center" Margin="5">
                <ContentControl ContentTemplate="{StaticResource DPersonInfoTmpl}" Content="{Binding}"/>
            </GroupBox>
            <GroupBox Header="绑定自己">
                <local:PersonInfoTest PersonName="{Binding Name}" PersonAge="{Binding Age}"/>
            </GroupBox>
        </StackPanel>
    </Grid>
</Window>

BehindCode:

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 MyWPFSimple2
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            m_VMMainWindow = DataContext as VMMainWindow;
        }

        private VMMainWindow m_VMMainWindow;
        private void btnShow_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("姓名:" + m_VMMainWindow.Name + "\r\n" + "年龄:" + m_VMMainWindow.Age, "信息");
        }
    }


    public class VMMainWindow : ObservableObject
    {
        public VMMainWindow()
        {
            Name = "令狐冲";
            Age = 25;
        }
        private string m_Name;
        public string Name
        {
            get { return m_Name; }
            set
            {
                m_Name = value;
                RaisePropertyChanged(nameof(Name));
            }
        }

        private int m_Age;
        public int Age
        {
            get { return m_Age; }
            set
            {
                m_Age = value;
                RaisePropertyChanged(nameof(Age));
            }
        }
    }
}

绑定 Window 的 DataContext

PersonInfo.xaml 控件

<UserControl x:Class="MyWPFSimple2.PersonInfo"
             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:MyWPFSimple2" 
             mc:Ignorable="d"  Background="LightBlue"
             d:DesignHeight="70" d:DesignWidth="200"
             DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext}"
             >
    
    <UserControl.Resources>
        <local:PerAgeConvert x:Key="agg_add_one"/>
        <local:PersonNameConvert x:Key="name_with_sub"/>
    </UserControl.Resources>

    <Grid>
        <StackPanel HorizontalAlignment="Center" Margin="5">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="姓名:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center"
                         Text="{Binding Name, Converter={StaticResource name_with_sub}}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0 2 0 0">
                <TextBlock Text="年龄:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center" 
                         Text="{Binding Age, Converter={StaticResource agg_add_one}}"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

BehindCode:

这种方式,没有 behindcode。

namespace MyWPFSimple2
{
    /// <summary>
    /// PersonInfo.xaml 的交互逻辑
    /// </summary>
    public partial class PersonInfo : UserControl
    {
        public PersonInfo()
        {
            InitializeComponent();
        }
    }     
}

散装

散装的就不说了。

数据模板 DataTemplate

这个也是直接找的 DataContext 绑定。

PersonInfoDTmpl.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:local="clr-namespace:MyWPFSimple2">

    <local:PerAgeConvert x:Key="agg_add_one"/>
    <local:PersonNameConvert x:Key="name_with_sub"/>

    <DataTemplate x:Key="DPersonInfoTmpl">
        <StackPanel HorizontalAlignment="Center" Margin="5">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="姓名:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center"
                         Text="{Binding Name}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0 2 0 0">
                <TextBlock Text="年龄:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center" 
                         Text="{Binding Age}"/>
            </StackPanel>
        </StackPanel>
    </DataTemplate>

</ResourceDictionary>

自定义依赖属性

这种方式,没有测试成功。 ViewModel 更改能通知到它,但它自己更改没有通知到 VM,有时间更熟悉WPF后再测试一下。

主界面绑定的是 clr 属性,而 UserControl 绑定的是 Property 属性, UserControl Property 更改的时候没有通知到 clr 属性,没能实现双向绑定。

PersonInfoTest.xaml

<UserControl x:Class="MyWPFSimple2.PersonInfoTest"
              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:MyWPFSimple2" 
             mc:Ignorable="d"  Background="LightPink"
             d:DesignHeight="70" d:DesignWidth="200"
            >

    <UserControl.Resources>
        <local:PerAgeConvert x:Key="agg_add_one"/>
        <local:PersonNameConvert x:Key="name_with_sub"/>
    </UserControl.Resources>

    <Grid>
        <StackPanel HorizontalAlignment="Center" Margin="5">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="姓名:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center"
                       Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=PersonName, Mode=TwoWay}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0 2 0 0">
                <TextBlock Text="年龄:" VerticalAlignment="Center"/>
                <TextBox BorderBrush="Black" Height="30" Width="150" VerticalContentAlignment="Center" 
                         Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=PersonAge, Mode=TwoWay}"/>
            </StackPanel>
        </StackPanel>
    </Grid>

</UserControl>

BehindCode:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
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 MyWPFSimple2
{
    /// <summary>
    /// PersonInfoTest.xaml 的交互逻辑
    /// </summary>
    public partial class PersonInfoTest : UserControl, INotifyPropertyChanged
    {
        public PersonInfoTest()
        {
            InitializeComponent();
            //DefaultStyleKeyProperty.OverrideMetadata(typeof(PersonInfoTest), new FrameworkPropertyMetadata(typeof(PersonInfoTest)));
        }

        public string PersonName
        {
            get
            {
                return (string)GetValue(PersonNameProperty);
            }
            set
            {
                SetValue(PersonNameProperty, value);
                RaisePropertyChanged(nameof(PersonName));
            }
        }

        // Using a DependencyProperty as the backing store for PersonName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PersonNameProperty =
            DependencyProperty.Register("PersonName", typeof(string), typeof(PersonInfoTest), new PropertyMetadata("悟空"));

        public int PersonAge
        {
            get
            {
                return (int)GetValue(PerAgeProperty);
            }
            set
            {
                SetValue(PerAgeProperty, value);
                RaisePropertyChanged(nameof(PersonAge));
            }
        }

        // Using a DependencyProperty as the backing store for PerAge.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PerAgeProperty =
            DependencyProperty.Register("PersonAge", typeof(int), typeof(PersonInfoTest), new PropertyMetadata(0));

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Convert.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace MyWPFSimple2
{
    public sealed class PersonNameConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string name = (string)value;
            return name + " 先生/女生";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string val = (string)value;
            return val.Split(' ')[0];
        }
    }

    public sealed class PerAgeConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int val = (int)value;
            return val + 1;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int val = int.Parse((string)value);
            return val - 1;
        }
    }
}

标签:控件,自定义,C#,object,System,value,Windows,using,public
From: https://www.cnblogs.com/huvjie/p/16909290.html

相关文章

  • C语言实验手册
    在三位整数(100~999)中寻找符合条件的整数,并以此从小到大存到数组当中,它既是完全平方数,又是两位数字相同,例如144,676等。#include<stdio.h>#include<math.h>intisSquare......
  • java——线程同步机制——解决线程安全问题——Lock锁
    解决线程安全问题——Lock锁解决线程安全问题的三种方案:使用Lock锁java.util.concurrent.locks.Lock接口Lock实现提供了比使用synchronized方法和语句可获得的更广......
  • Docker-网络模式
    1.docker-网络模式网络模式简介bridge为每一个容器分配、设置IP等、并将容器连接到一个docker0中、这个叫虚拟网桥,默认为该模式host容器将不会虚拟出自己......
  • CF1695E Ambiguous Dominoes
    CF1695EAmbiguousDominoes如下图,给定\(n\)个\(1\times2\)的多米诺骨牌,每个骨牌两边均写有数字,求一种矩形的构造方案,使得存在\(2\)种不同的方法将多米诺放进矩形......
  • 「NOIP赛前冲刺」ABC278F
    Solution简单状态压缩,考虑设\(f_{S,i}\)表示状态为\(S\)并且当前要求一个开头为\(s_i\)的结尾字符的单词,\(\text{First}\)如果能赢为\(0\),否则为\(1\)。那么很......
  • vs2022 使用 cmake
    vs版本:vs2022vs中默认不使用cmake,在项目->cmake工作区设置中修改{"enableCMake":flase}默认为false,修改为true即可。点击CMakeLists.txt文件设置启动项,......
  • k8s源码分析3-kubectl命令行设置7大命令分组
    本节重点总结:设置cmd工厂函数f,主要是封装了与kube-apiserver交互客户端用cmd工厂函数f创建7大分组命令,如下基础初级命令BasicCommands(Beginner):基础中级命......
  • 从Scratch 2学到的一些编程思想
    从Scratch2学到的一些编程思想所有程序都是事件驱动的mingdu.zhengatgmaildotcomScratch是麻省理工大学(MIT)为8~16岁的孩子开发的编程工具。Scratch的基本原理是为所选......
  • P7163 [COCI2020-2021#2] Svjetlo
    题意给你一棵点权是\(0/1\)的树,你可以从任意一点开始,走到任意一点结束,每到达一个点,都要翻转当前的点权。给定初始的点权,求使得整棵树的点权都变成\(1\)的最短路径长度......
  • Ubuntu 16.04安装Brackets 1.7失败,缺失libgcrypt11,解决办法
    Ubuntu16.04安装Brackets1.7失败,缺失libgcrypt11,解决办法mingdu.zhengatgmaildotcom问题Ubuntu16.04安装Brackets1.7失败,提示缺失libgcrypt11。sudodpkg-iBracke......