Press "Enter" to skip to content

Wszystko pod kontrolką

Dobra, dziś w ramach konkursu „Daj się poznać” pokażę, jak zrobić zajebistą kontrolkę, w pełni responsywną z naszą aplikacją.

Kontrolka jest kawałkiem interfejsu graficznego, który upraszcza nam projektowanie tegoż. Raz napisana przez kogoś (na przykład przez nas) może być użyta wiele razy w różnych oknach. Najprościej jest złożyć kontrolkę z kilku innych kontrolek i dokonać na nich pewną akcję.

W wielu miejscach jest sytuacja, że mamy jakiś ciąg kontrolek które występują koło siebie. I tak powstaje „kandydat na kontrolkę. Złowiłam takiego także u siebie, i to już w jednym oknie:

Zasada DRY mówi o tym, aby się nie powtarzać. Dlatego powtarzające się kawałki kodu ładujemy do funkcji, zaś powtarzające się kawałki interfejsu ładujemy do kontrolek.

Czego na początku od niej wymagamy? Mamy sobie textblock i textbox, którego rozmiary mają mieć możliwość dostosowania się do miejsca jakie mu damy. Chcemy też mieć możliwość ustawienia tekstu w opisie bezpośrednio z poziomu xaml oraz chcemy być informowani o zmianie tekstu w textboxie. Chcemy także, aby działał podgląd w visual studio i tyle. Starczy.

Przykładowe użycie w oknie ma się przedstawiać następująco:

 

Zacznijmy od pliku .xaml dla kontrolki:

<UserControl x:Class="bezpieczniejsi.DescTextBox"
             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:bezpieczniejsi"
             mc:Ignorable="d" 
           >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock x:Name="InputBox" TextWrapping="Wrap" Text="" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <TextBox x:Name="OutputBox" Grid.Column="1" TextWrapping="Wrap" Text="" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" TextChanged="OutputBox_TextChanged" GotFocus="OutputBox_GotFocus"/>
    </Grid>

Proszę zauważyć, że linijka d:DesignHeight=”300″ d:DesignWidth=”300″ z góry została celowo usunięta, abyśmy uzyskali rzeczywisty podgląd.

Kod .cs kontrolki wygląda następująco:

 public partial class DescTextBox : UserControl
    {
       
        public DescTextBox()
        {
            InitializeComponent();
        }



        public string Input
        {
            get { return (string)GetValue(InputProperty); }
            set
            {
                SetValue(InputProperty, value);
                InputBox.Text = value;
            }
        }

        public static readonly DependencyProperty InputProperty =
            DependencyProperty.Register("Input", typeof(string), typeof(DescTextBox), new PropertyMetadata(string.Empty, InputValueChanged));

        private static void InputValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as DescTextBox;
            if (control == null) return;
            control.InputBox.Text = e.NewValue.ToString();
        }
        public delegate void OutputEventHandler(object sender, StringChangedEventArgs args);
        StringChangedEventArgs args = new StringChangedEventArgs();
        public event OutputEventHandler OutputChanged;
        string _previousText = string.Empty;
        private void OutputBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            args.NewValue = OutputBox.Text;
            args.OldValue = _previousText;
            OutputChanged?.Invoke(this, args);
        }

        private void OutputBox_GotFocus(object sender, RoutedEventArgs e)
        {
            _previousText = OutputBox.Text;
        }
    }

Aby móc mieć dostęp z xaml użyto mechanizmu DependencyProperty (jak nie wiesz jak ręcznie ogarnąć- wpisz propd i wciśnij tab 2 razy), zaś zmiana tekstu jest realizowana jako event zdefiniowany przez użytkownika. Można albo przez xamla podać nazwę funkcji, albo przez += z poziomu kodu.

Kontrolka działa, co można zobaczyć otwierając ThreeGrade.xaml dostępnego gdzieś w projekcie umieszczonym na https://github.com/Piatkosia/bezpieczniejsi.

5 komentarzy

  1. Wszystko pod kontrolką – Zagubiona wśród własnych myśli – Piatkosia’s blog

    Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl

    • ja ja

      Ooo dzięki:)

  2. Zgodnie z DRY, można wykorzystać HeaderedContentControl, który jest „wbudowany” w WPFa.

    I poprzez podmianę templatów dojść do tego samego.

    • ja ja

      Ooo, fajny patent, nie znałam:). Dzięki.

Comments are closed.