WPF ile DigitTextBox

by Timur 10. Ocak 2012 17:58

Öncelikle herkese merhaba.

Herşeyin başı merak dedim ve hiç lazım olmadığı halde WPF içerisinde CustomControl yazma işine merak sardım. Bu merak sonucundaki ilk çıktıyı da paylaşmak istedim. İlk denemem sadece sayıların girilebileceği bir DigitTextBox olacak.

Bunun için yaratacağımız sınıfı "Control" sınıfından türetiyoruz. Ayrıca bu kontrolümüzü dizayn edebilmek için "Themes" klasörünün altına "Generic.xaml" dosyasını oluşturup dizayn işlemine başlıyoruz.

 

Yazacağımız digittextbox için bir adet textbox, iki adet de butona ihtiyacımız var. Bunları görmek istediğimiz şekilde "Generic.xaml" dosyasında tanımlıyoruz.

 

<ResourceDictionary

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="clr-namespace:DebugControls.DebugDigitTextbox">

    <Style TargetType="{x:Type local:DebugDigitTextBox}">

        <Setter Property="Template">

            <Setter.Value>

                <ControlTemplate TargetType="{x:Type local:DebugDigitTextBox}">

                    <Border Background="{TemplateBinding Background}"

                            BorderBrush="{TemplateBinding BorderBrush}"

                            BorderThickness="{TemplateBinding BorderThickness}">

						<Grid>

							<Grid.ColumnDefinitions>

								<ColumnDefinition Width="*"></ColumnDefinition>

								<ColumnDefinition Width="Auto"></ColumnDefinition>

							</Grid.ColumnDefinitions>

							<TextBox x:Name="TemplateTextbox" Grid.Column="0"></TextBox>

							<Grid Grid.Column="1">

								<Grid.RowDefinitions>

									<RowDefinition></RowDefinition>

									<RowDefinition></RowDefinition>

								</Grid.RowDefinitions>

								<Button x:Name="IncrementButton" Grid.Row="0"

										Margin="1,1,1,1">

									<TextBlock                                                    

                                        Text="p"                                                    

                                        FontFamily="Wingdings 3"

                                        FontSize="6"

                                        HorizontalAlignment="Center"

                                        VerticalAlignment="Center"/>

								</Button>

								<Button x:Name="DecrementButton" Grid.Row="1"

										Margin="1,1,1,1">

									<TextBlock                                                    

                                        Text="q"                                                    

                                        FontFamily="Wingdings 3"

                                        FontSize="6"

                                        HorizontalAlignment="Center"

                                        VerticalAlignment="Center"/>

								</Button>

							</Grid>

						</Grid>

					</Border>

                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

</ResourceDictionary>
 
Daha sonra ilk yapacağımız işlerdne biri Template Apply olduğu anda kontrolümüzdeki textbox ve butonları alıp, gerekli eventleri yakalamak.
 
public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			if (_IncrementButton != null)
			{
				_IncrementButton.Click -= _IncrementButtonClick;
			}

			if (_DecrementButton != null)
			{
				_DecrementButton.Click -= _DecrementButtonClick;
			}

			if (_TextBox != null)
			{
				_TextBox.PreviewTextInput -= _TextBoxKeyDown;
				_TextBox.TextChanged -= _TextBoxTextChanged;
				_TextBox.PreviewKeyDown -= _TextBoxPreviewKeyDown;
			}

			_TextBox = GetTemplateChild(TextboxName) as TextBox;
			_IncrementButton = GetTemplateChild(IncrementButtonName) as Button;
			_DecrementButton = GetTemplateChild(DecrementButtonName) as Button;

			_IncrementButton.Click += _IncrementButtonClick;
			_DecrementButton.Click += _DecrementButtonClick;
			_TextBox.PreviewTextInput += _TextBoxKeyDown;
			_TextBox.TextChanged += _TextBoxTextChanged;
			_TextBox.PreviewKeyDown += _TextBoxPreviewKeyDown;
		}

Diğer önemli bir nokta ise kontrolün static constructor ında base sınıftan gelen "DefaultKeyStyle" ı override etmek.

 

static DebugDigitTextBox()

{

	DefaultStyleKeyProperty.OverrideMetadata(typeof(DebugDigitTextBox), new FrameworkPropertyMetadata(typeof(DebugDigitTextBox)));

}

 

Geriye kalan ise eventleri yakalayıp, gerekli işlemleri yapabilmek...

 

public class DebugDigitTextBox : Control

	{

		#region Events

		public event RoutedPropertyChangedEventHandler<TimeSpan> ValueChanged

		{

			add { base.AddHandler(ValueChangedEvent, value); }

			remove { base.RemoveHandler(ValueChangedEvent, value); }

		}



		public static readonly RoutedEvent ValueChangedEvent =

			EventManager.RegisterRoutedEvent(

			"ValueChanged",

			RoutingStrategy.Bubble,

			typeof(RoutedPropertyChangedEventHandler<int>),

			typeof(DebugDigitTextBox));

		#endregion



		#region Members

		TextBox _TextBox;

		Button _IncrementButton;

		Button _DecrementButton;



		const string TextboxName = "TemplateTextbox";

		const string IncrementButtonName = "IncrementButton";

		const string DecrementButtonName = "DecrementButton";

		#endregion



		#region DependencyProperties

		public static DependencyProperty ValueProperty = DependencyProperty.Register(

			"Value", typeof(int), typeof(DebugDigitTextBox), new PropertyMetadata(0, DebugDigitTextBox.OnValueChanged, null));

		#endregion



		#region Properties

		public int Value

		{

			get { return Convert.ToInt32(GetValue(ValueProperty)); }

			set

			{

				if (Convert.ToInt32(GetValue(ValueProperty)) == value)

					return;

				SetValue(ValueProperty, value);

			}

		}

		#endregion



		#region Initialization

		static DebugDigitTextBox()

		{

			DefaultStyleKeyProperty.OverrideMetadata(typeof(DebugDigitTextBox), new FrameworkPropertyMetadata(typeof(DebugDigitTextBox)));

		}



		public DebugDigitTextBox()

		{

			Value = 0;

			Width = 100;

		}

		#endregion



		#region Methods

		private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)

		{

			DebugDigitTextBox textBox = obj as DebugDigitTextBox;

			if (textBox != null)

			{

				textBox.OnValueChanged((int)e.OldValue, (int)e.NewValue);

			}

		}



		void _IncrementButtonClick(object sender, RoutedEventArgs e)

		{

			Value++;

		}



		void _DecrementButtonClick(object sender, RoutedEventArgs e)

		{

			Value--;

		}



		void _TextBoxKeyDown(object sender, TextCompositionEventArgs e)

		{

			if (e.Text.Length == 1)

			{

				if (e.Text[0] == '-')

				{

					Value = Value * -1;

					e.Handled = true;

					return;

				}

				else if (!char.IsDigit(e.Text[0]))

				{

					e.Handled = true;

					return;

				}

			}

		}



		void _TextBoxTextChanged(object sender, TextChangedEventArgs e)

		{

			if (string.IsNullOrEmpty(_TextBox.Text))

			{

				Value = 0;

			}

			else if (_TextBox.Text == "-")

			{

				Value = 0;

			}

			else

			{

				try

				{

					Value = Convert.ToInt32(_TextBox.Text);

				}

				catch

				{

					_TextBox.Text = _TextBox.Text.Remove(_TextBox.SelectionStart - 1, 1);

					e.Handled = true;

					return;

				}

			}

			if (Value == 0)

			{

				_TextBox.Text = Value.ToString();

			}

		}



		void _TextBoxPreviewKeyDown(object sender, KeyEventArgs e)

		{

			if (e.Key == Key.Down)

			{

				Value = Value - 1;

			}

			else if (e.Key == Key.Up)

			{

				Value = Value + 1;

			}

		}



		protected virtual void OnValueChanged(int oldValue, int newValue)

		{

			_TextBox.Text = Value.ToString();

			RoutedPropertyChangedEventArgs<int> e = new RoutedPropertyChangedEventArgs<int>(oldValue, newValue);

			e.RoutedEvent = ValueChangedEvent;

			base.RaiseEvent(e);

		}



		public override void OnApplyTemplate()

		{

			base.OnApplyTemplate();



			if (_IncrementButton != null)

			{

				_IncrementButton.Click -= _IncrementButtonClick;

			}



			if (_DecrementButton != null)

			{

				_DecrementButton.Click -= _DecrementButtonClick;

			}



			if (_TextBox != null)

			{

				_TextBox.PreviewTextInput -= _TextBoxKeyDown;

				_TextBox.TextChanged -= _TextBoxTextChanged;

				_TextBox.PreviewKeyDown -= _TextBoxPreviewKeyDown;

			}



			_TextBox = GetTemplateChild(TextboxName) as TextBox;

			_IncrementButton = GetTemplateChild(IncrementButtonName) as Button;

			_DecrementButton = GetTemplateChild(DecrementButtonName) as Button;



			_IncrementButton.Click += _IncrementButtonClick;

			_DecrementButton.Click += _DecrementButtonClick;

			_TextBox.PreviewTextInput += _TextBoxKeyDown;

			_TextBox.TextChanged += _TextBoxTextChanged;

			_TextBox.PreviewKeyDown += _TextBoxPreviewKeyDown;

		}

		#endregion

	}

 

İyi çalışmalar herkeslere...

Tags: , , ,

Yorum ekle

  Country flag

biuquote
  • Yorum
  • Canlı önizleme
Loading

Hakkımda

Evli, mutlu, çocuksuz...

Bilgisayar Mühendisi...

.Net Developer...

Crs Soft