TOC

This article is currently in the process of being translated into Vietnamese (~99% done).

Misc. controls:

The Slider control

Điều khiển Thanh trượt (Slider control) cho phép bạn chọn một giá trị số bằng cách kéo thả con trỏ theo chiều ngang hoặc chiều dọc. Bạn thấy nó trong nhiều giao diện người dùng nhưng có vẻ hơi khó hiểu với mô tả trên, nên hay coi ví dụ đơn giản sau:

<Window x:Class="WpfTutorialSamples.Misc_controls.SliderSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SliderSample" Height="100" Width="300">
    <StackPanel VerticalAlignment="Center" Margin="10">
        <Slider Maximum="100" />
    </StackPanel>
</Window>

Điều này sẽ cho phép người dùng chọn giữa các giá trị từ 0 đến 100 bằng cách kéo nút (tượng trưng cho con trỏ) dọc theo dòng kẻ.

Các vạch chia giá trị

Trong ví dụ này, tôi đã kéo thả con trỏ vào giữa, rõ ràng là rất khó để xác định đúng giá trị. Có một cách khác phục đó là bật các vạch chia giá trị, đó là những điểm đánh dấu nhỏ được hiển thị trên dòng kẻ nhằm đưa ra những dấu hiệu rõ hơn về khoảng cách của con trỏ. Đây là ví dụ:

<Window x:Class="WpfTutorialSamples.Misc_controls.SliderSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SliderSample" Height="100" Width="300">
    <StackPanel VerticalAlignment="Center" Margin="10">
        <Slider Maximum="100" TickPlacement="BottomRight" TickFrequency="5" />
    </StackPanel>
</Window>

Tôi bật những cái vạch chia giá trị lên bằng cách cho vào thuộc tính TickPlacement một giá trị khác không (giá trị mặc định). Trong ví dụ của tôi, tôi muốn các vạch này được đặt bên dưới dòng kẻ thẳng nhưng bạn cũng có thể dùng TopLeft hoặc là Both đều phù hợp.

Cũng chú ý là tôi có sử dụng thuộc tính TickFrequency. Giá trị mặc định của thuộc tính này là 1, nhưng trong ví dụ này, phạm vi giá trị là từ 0 đến 100, nghĩa là sẽ có 100 vạch nhỏ được đặt vào một không gian giới hạn. Trong trường hợp này, sẽ hợp lý nếu nâng giá trị của TickFrequency lên sẽ giúp dễ nhìn hơn.

Đánh dấu nhanh (Snapping to ticks)

Nếu bạn nhìn vào ảnh ví dụ phía trên, bạn sẽ thấy rằng là con trỏ đang chỉ vào giữa 2 vạch. Để cho dễ hiểu, vì giá trị của thuộc tính TickFrequency là 5 nên sẽ có 5 giá trị con nữa mỗi vạch. Ngoài ra, giá trị của Slider control trên thực tế theo mặc định là gấp đôi, nghĩa là giá trị có thể (có khả năng) không phải là một số nguyên. Chúng ta sẽ thay đổi điều này bằng cách dùng thuộc tính IsSnapToTickEnabled, xem ví dụ ở bên dưới:

<Window x:Class="WpfTutorialSamples.Misc_controls.SliderSnapToTickSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SliderSnapToTickSample" Height="100" Width="300">
    <StackPanel VerticalAlignment="Center" Margin="10">
        <Slider Maximum="100" TickPlacement="BottomRight" TickFrequency="10" IsSnapToTickEnabled="True" />
    </StackPanel>
</Window>

Chú ý là tôi đã tăng TickFrequency lên 10 và sau đó kích hoạt thuộc tính IsSnapToTickEnabled. Điều này đảm bảo rằng con trỏ sẽ chỉ trực tiếp vào một vạch cụ thể, vì vậy với ví dụ này chỉ có thể là 0, 10, 20, 30, 40...v.v.

Giá trị Thanh trượt

Đến hiện tại thì chúng ta đã dùng Thanh trượt (Slider) một cách khá linh hoạt, tuy nhiên, mục đích thực tế là để giá trị hiện tại và dùng cho một việc gì đó. Thanh trượt có thuộc tính Value cho việc đó, tất nhiên bạn có thể đọc nó từ Code-behind hoặc là gán cho nó.

Tình huống phổ biến là khi dùng Slider sẽ đi kèm với textbox để người dùng có thể xem giá trị hiện tại đang được chọn, cũng như thay đổi giá trị bằng cách nhập giá trị mới vào ô Textbox mà không cần phải kéo thả con trỏ Slider. Thông thường, bạn sẽ phải khai báo để thay đổi các sự kiện ở cả Slider và Textbox và cập nhật tương ứng, nhưng có một phép gán liên tục có thể làm tất cả cho chúng ta:

<Window x:Class="WpfTutorialSamples.Misc_controls.SliderBoundValueSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SliderBoundValueSample" Height="100" Width="300">
    <DockPanel VerticalAlignment="Center" Margin="10">
        <TextBox Text="{Binding ElementName=slValue, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
        <Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slValue" />
    </DockPanel>
</Window>

Bây giờ bạn có thể thay đổi giá trị bằng cách dùng Slider hoặc nhập giá trị vào ô Textbox, và sẽ có phản hồi ngay lập tức trong các điều khiển (control) khác. Bonus thêm, chúng ta cũng vừa có được một cách xác minh xem giá trị nhập vào Textbox có phải là số hay các ký tự không phải số mà không cần phải làm thêm bất cứ công việc nào:

Phản ứng với các giá trị được thay đổi

Tất nhiên, ngoài việc ràng buộc rất tuyệt cho nhiều mục đích, bạn vẫn muốn có phản hồi khi các giá trị Slider thay đổi từ Code-behind của bạn. May mắn cho chúng ta, Slider có đi kèm với sự kiện ValueChanged, thứ mà sẽ giúp chúng ta làm việc đó. Để minh họa, tôi đã làm một ví dụ phức tạp hơn với 3 thanh trượt để thay đổi các giá trị Đỏ (Red), Lục (Green) và Lam (Blue) (hay còn gọi là RGB) của một màu:

<Window x:Class="WpfTutorialSamples.Misc_controls.SliderValueChangedSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SliderValueChangedSample" Height="200" Width="300">
    <StackPanel Margin="10" VerticalAlignment="Center">
        <DockPanel VerticalAlignment="Center" Margin="10">
            <Label DockPanel.Dock="Left" FontWeight="Bold">R:</Label>
            <TextBox Text="{Binding ElementName=slColorR, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
            <Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorR" ValueChanged="ColorSlider_ValueChanged" />
        </DockPanel>

        <DockPanel VerticalAlignment="Center" Margin="10">
            <Label DockPanel.Dock="Left" FontWeight="Bold">G:</Label>
            <TextBox Text="{Binding ElementName=slColorG, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
            <Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorG" ValueChanged="ColorSlider_ValueChanged" />
        </DockPanel>

        <DockPanel VerticalAlignment="Center" Margin="10">
            <Label DockPanel.Dock="Left" FontWeight="Bold">B:</Label>
            <TextBox Text="{Binding ElementName=slColorB, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
            <Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorB" ValueChanged="ColorSlider_ValueChanged" />
        </DockPanel>
    </StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Media;

namespace WpfTutorialSamples.Misc_controls
{
	public partial class SliderValueChangedSample : Window
	{
		public SliderValueChangedSample()
		{
			InitializeComponent();
		}

		private void ColorSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			Color color = Color.FromRgb((byte)slColorR.Value, (byte)slColorG.Value, (byte)slColorB.Value);
			this.Background = new SolidColorBrush(color);
		}
	}
}

Trong phần code XAML, tôi có 3 DockPanels, mỗi cái đi cùng với 1 Label, 1 Slider và một Textbox control. Giống như ví dụ trước, thuộc tính Text của Textbox controls sẽ được liên kết với giá trị của Thanh trượt (Slider).

Mỗi thanh trượt sẽ khai báo cùng một sự kiện ValueChanged, trong đó chúng ta sẽ tạo một đối tượng Màu mới dựa trên giá trị được chọn hiện tại, sau đó dùng chính màu đó để tạo một SolidColorBrush mới cho thuộc tính Background của cửa sổ.

Tựu chung, đây là một ví dụ rất rất hay về những gì Slider control có thể được sử dụng.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!