其他分享
首页 > 其他分享> > ReactiveX 学习笔记(32)使用 Rx.NET + ReactiveUI 实现自定义控件

ReactiveX 学习笔记(32)使用 Rx.NET + ReactiveUI 实现自定义控件

作者:互联网

课题

  1. 自定义控件界面由3个文本编辑框和2个文本标签组成。
  2. 3个文本编辑框分别表示时分秒,只能输入数字,上下限分别为 0~23,0~59,0~59。
  3. 2个文本标签充当间隔符,只显示字符 ":"。
  4. 自定义控件向外界公开一个名为 Value 的属性,实时反映所输入的时分秒所代表的的秒数:时 * 3600 + 分 * 60 + 秒。

创建工程

打开 Visual Studio,File / New / Project...
新建一个名为 RxExample 的 WPF 应用程序。

ReactiveUI

打开 NuGet 包管理器,搜索并安装以下三个包。
ReactiveUI
ReactiveUI.Fody
Extended.Wpf.Toolkit

TimeSpanUpDown

在工程中添加名为 TimeSpanUpDown 的 UserControl 子类(添加新项目,选择 User Control)。

将 TimeSpanUpDown.xaml 内容改为

<UserControl
             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:RxExample"
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" x:Class="RxExample.TimeSpanUpDown"
             mc:Ignorable="d" 
             d:DesignHeight="20" d:DesignWidth="150">
    <UserControl.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="Margin" Value="5 0 5 0" />
        </Style>
    </UserControl.Resources>
    <Grid x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <xctk:UShortUpDown Value="{Binding Hour}" Maximum="23" Grid.Column="0"/>
        <TextBlock Text=":" Grid.Column="1" />
        <xctk:UShortUpDown Value="{Binding Minute}" Maximum="59" Grid.Column="2"/>
        <TextBlock Text=":" Grid.Column="3" />
        <xctk:UShortUpDown Value="{Binding Second}" Maximum="59" Grid.Column="4"/>
    </Grid>
</UserControl>

将 TimeSpanUpDown.xaml.cs 内容改为

using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;

namespace RxExample
{
    public partial class TimeSpanUpDown : UserControl
    {
        public TimeSpanUpDownViewModel VM { get; } = new TimeSpanUpDownViewModel();

        public int Value
        {
            get => (int)GetValue(ValueProperty);
            set => SetValue(ValueProperty, value);
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(int), typeof(TimeSpanUpDown),
                new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ValuePropertyChangedCallback));

        private static void ValuePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as TimeSpanUpDown;
            control.VM.SetValue(control.Value);
        }

        public TimeSpanUpDown()
        {
            InitializeComponent();
            grid.DataContext = VM;
            VM.ValueChanged.Subscribe(value => SetValue(ValueProperty, value));
        }
    }
    public class TimeSpanUpDownViewModel : ReactiveObject
    {
        [Reactive]
        public int Hour { get; set; }
        [Reactive]
        public int Minute { get; set; }
        [Reactive]
        public int Second { get; set; }
        public IObservable<int> ValueChanged;
        public void SetValue(int value)
        {
            Hour = value / 3600;
            Minute = value / 60 % 60;
            Second = value % 60;
        }
        public TimeSpanUpDownViewModel()
        {
            ValueChanged = this.WhenAnyValue(x => x.Hour, x => x.Minute, x => x.Second, (h, m, s) => h * 3600 + m * 60 + s);
        }
    }
}

使用自定义控件

在 MainWindow.xaml 中添加以下两个标签

<local:TimeSpanUpDown x:Name="x" />
<TextBlock x:Name="y" Text="{Binding ElementName=x,Path=Value}" />

程序运行后可以发现名为 y 的文本框会实时反映名为 x 的自定义控件中所代表的秒数

标签:控件,TimeSpanUpDown,自定义,int,32,value,ReactiveUI,using,public
来源: https://www.cnblogs.com/zwvista/p/12931952.html