Denetim yazma genel bakış
Windows Presentation Foundation (WPF) denetim modelinin genişletilebilirliği, yeni bir denetim oluşturma gereksinimini büyük ölçüde azaltır. Ancak bazı durumlarda, hala özel bir denetim oluşturmanız gerekebilir. bu konuda, Windows Presentation Foundation (WPF) içinde özel bir denetim ve farklı denetim yazma modellerini oluşturma gereksiniminizi en aza indirecek özellikler açıklanmaktadır. Bu konuda ayrıca nasıl yeni bir denetim oluşturacağınız gösterilmektedir.
Yeni denetim yazma alternatifleri
Tarihsel olarak, var olan bir denetimden özelleştirilmiş bir deneyim almak isterseniz, denetimin, arka plan rengi, kenarlık genişliği ve yazı tipi boyutu gibi standart özelliklerini değiştirmekle sınırlı olursunuz. Bir denetimin görünüşünü veya davranışını bu önceden tanımlanmış parametrelerin ötesinde uzatmak istiyorsanız, genellikle var olan bir denetimden devralarak ve denetimi çizmekten sorumlu yöntemi geçersiz kılarak yeni bir denetim oluşturmanız gerekir. Yine de bir seçenek olsa da WPF, zengin içerik modeli, stilleri, şablonları ve Tetikleyicileri kullanarak var olan denetimleri özelleştirmenize olanak sağlar. Aşağıdaki listede, bu özelliklerin yeni bir denetim oluşturmak zorunda kalmadan özel ve tutarlı deneyimler oluşturmak için nasıl kullanılabileceği hakkında örnekler verilmektedir.
Zengin Içerik. Standart WPF denetimlerinin birçoğu zengin içerikleri destekler. Örneğin, öğesinin içerik özelliği Button türündedir Object , bu nedenle teorik olarak her şey bir üzerinde görüntülenebilir Button . Bir düğmenin bir görüntü ve metin görüntülemesi için, bir görüntü ve a ekleyebilir TextBlockStackPanel ve StackPanelContent özelliğini özelliğine atayabilirsiniz. Denetimler WPF görsel öğelerini ve isteğe bağlı verileri görüntüleyebilen için, yeni bir denetim oluşturmanız veya var olan bir denetimi karmaşık görselleştirmeyi destekleyecek şekilde değiştirmenize gerek yoktur. WPF 'deki içerik modeli ve diğer içerik modelleri hakkında daha fazla bilgi için Button bkz. Button.
Stillerde. Style, Bir denetimin özelliklerini temsil eden bir değerler koleksiyonudur. Stilleri kullanarak, istenen denetim görünümü ve davranışı için yeni bir denetim yazmadan yeniden kullanılabilir bir temsili oluşturabilirsiniz. Örneğin, tüm TextBlock denetimlerinizin, 14 yazı tipi boyutuyla kırmızı, Arial yazı tipine sahip olmasını istediğinizi varsayalım. Kaynak olarak bir stil oluşturabilir ve uygun özellikleri uygun şekilde ayarlayabilirsiniz. Sonra TextBlock uygulamanıza eklediğiniz her bir görünüm aynı olur.
Veri şablonları. Bir DataTemplate denetimde verilerin nasıl görüntülendiğini özelleştirmenizi sağlar. Örneğin, bir, ' DataTemplate de verilerin nasıl görüntüleneceğini belirtmek için kullanılabilir ListBox . Buna bir örnek için bkz. veri şablonu oluşturmaya genel bakış. Verilerin görünümünü özelleştirmenin yanı sıra, DataTemplate özel uıof 'ta çok sayıda esneklik sağlayan UI öğeleri içerebilir. Örneğin, bir kullanarak DataTemplate , ComboBox her bir öğenin bir onay kutusu içerdiği bir oluşturabilirsiniz.
Denetim şablonları. WPF 'deki pek çok denetim, denetimin işlevselliğiyle bir denetimin ControlTemplate görünüşünü ayıran denetimin yapısını ve görünümünü tanımlamak için bir kullanır. Denetimin görünümünü büyük ölçüde tekrar tanımlayarak değiştirebilirsiniz ControlTemplate . Örneğin, bir denetim ışığı gibi görünen bir denetim istediğinizi varsayalım. Bu denetimde basit bir kullanıcı arabirimi ve işlevselliği vardır. Denetim üç dairedir, tek seferde yalnızca bir tane olabilir. Bazı yansımalardan sonra, bir RadioButton kerede yalnızca bir tane seçilmekte olan işlevi sunduğunu fark edebilirsiniz, ancak varsayılan görünümü bir RadioButton trafik ışığı üzerindeki ışıklar gibi görünmüyor. , RadioButton Görünümünü tanımlamak için bir denetim şablonu kullandığından, ControlTemplate denetimin gereksinimlerine uyacak şekilde öğesini yeniden tanımlamak ve trafik durma alanınızı açmak için radyo düğmelerini kullanmak kolaydır.
Not
, Bir RadioButton kullanabilir ancak DataTemplate , DataTemplate Bu örnekte yeterli değildir. , DataTemplate Bir denetimin içeriğinin görünümünü tanımlar. Bir durumunda RadioButton , içerik seçili olup olmadığını gösteren dairenin sağında görüntülenir RadioButton . Trafik ışığı örneğinde radyo düğmesi yalnızca "hafif" bir daire olmalıdır. Durma ışığı için görünüm gereksinimi, ' nin varsayılan görünümüyle farklı olduğundan, RadioButton öğesini yeniden tanımlamak gerekir ControlTemplate . Genel a DataTemplate , bir denetimin içeriğini (veya verilerini) tanımlamak için kullanılır ve bir ControlTemplate denetimin nasıl yapılandırıldığını tanımlamak için kullanılır.
Tetikleyiciler. Trigger, Bir denetimin görünümünü ve davranışını yeni bir denetim oluşturmadan dinamik olarak değiştirmenize olanak sağlar. Örneğin, uygulamanızda birden çok ListBox denetiminizin olduğunu ve her birinin ListBox seçildikleri zaman kalın ve kırmızı olmasını istediğinizi varsayalım. İlk işlem, ' den devralan bir sınıf oluşturmak ListBox ve OnSelectionChanged Seçilen öğenin görünümünü değiştirmek için yöntemini geçersiz kılmak, ancak daha iyi bir yaklaşım, ListBoxItem Seçilen öğenin görünümünü değiştiren bir öğesinin stiline bir tetikleyici eklemektir. Tetikleyici, özellik değerlerini değiştirmenize veya bir özelliğin değerine göre eylem yapmanıza olanak sağlar. Bir EventTrigger olay gerçekleştiğinde eylemler gerçekleştirmenizi sağlar.
Stiller, şablonlar ve Tetikleyiciler hakkında daha fazla bilgi için bkz. Stil oluşturma ve şablonoluşturma.
Genel olarak, denetiminiz var olan bir denetimin işlevselliğini yansıtır, ancak denetimin farklı görünmesini istiyorsanız, bu bölümde açıklanan yöntemlerden herhangi birini kullanıp kullanmayacağınızı, var olan denetimin görünümünü değiştirmek için göz önünde bulundurmanız gerekir.
Denetim yazma modelleri
Zengin içerik modeli, stiller, şablonlar ve Tetikleyiciler, yeni bir denetim oluşturmanız gereksinimini en aza indirir. Ancak, yeni bir denetim oluşturmanız gerekiyorsa, WPF 'de farklı denetim yazma modellerinin anlaşılması önemlidir. WPF, her biri farklı bir özellik kümesi ve esneklik düzeyi sağlayan denetim oluşturmak için üç genel model sağlar. Üç modelin temel sınıfları, ve ' dir UserControlControlFrameworkElement .
UserControl 'ten türetme
WPF 'de bir denetim oluşturmanın en kolay yolu, ' den türetmektir UserControl . Öğesinden devralan bir denetim oluşturduğunuzda, UserControl var olan bileşenleri UserControl içine ekleyin, bileşenleri adlandırın ve EXTENSIBLE APPLICATION MARKUP Language (XAML) içindeki olay işleyicilerini başvuru işleyicileri. Daha sonra adlandırılmış öğelere başvurabilir ve koddaki olay işleyicilerini tanımlayabilirsiniz. Bu geliştirme modeli, WPF 'de uygulama geliştirme için kullanılan modele çok benzer.
Doğru şekilde oluşturulıyorsa, UserControl zengin içerik, stiller ve tetikleyicilerin avantajlarından faydalanabilirsiniz. Ancak, denetiminiz öğesinden devralırsa UserControl , denetiminizi kullanan kişiler DataTemplateControlTemplate görünümünü özelleştirmek için bir veya kullanamaz. ControlUserControl Şablonları destekleyen özel bir denetim oluşturmak için sınıfından veya türetilmiş sınıflarından birinden (dışında) türetmeniz gerekir.
UserControl 'dan Türetmenin avantajları
Aşağıdakilerin tümü uygulandıysanız ' dan türetmeyi göz önünde bulundurun UserControl :
Bir uygulamayı nasıl derlemenize benzer şekilde denetiminizi oluşturmak istersiniz.
Denetiminiz yalnızca mevcut bileşenlerden oluşur.
Karmaşık özelleştirmeyi desteklemek zorunda değilsiniz.
Denetimden türetme
Sınıfından türetmek, Control mevcut WPF denetimlerinin çoğu tarafından kullanılan modeldir. Sınıfından devralan bir denetim oluşturduğunuzda Control , görünümünü şablonlar kullanarak tanımlarsınız. Bunu yaptığınızda, işlemsel mantığı görsel gösterimden ayırdığınızda. Ayrıca, olaylar yerine komutları ve bağlamaları kullanarak ve mümkün olan her durumda öğelere başvurmaktan kaçınarak UI ve mantığın ayrılmasıyla emin olabilirsiniz ControlTemplate . Denetiminizin kullanıcı ARABIRIMI ve mantığı düzgün şekilde ayrıldıysanız, denetiminizin bir kullanıcısı, ControlTemplate görünümünü özelleştirmek için denetimi yeniden tanımlayabilir. Özel derleme, oluşturma Control kadar basit olmasa da UserControl , özel bir Control en esnekliği sağlar.
Denetimden Türetmenin avantajları
ControlAşağıdakilerden birini uyguladığınızda sınıfını kullanmak yerine ' den türetmeyi göz önünde bulundurun UserControl :
Denetiminizin görünümünün aracılığıyla özelleştirilebilir olmasını istiyorsunuz ControlTemplate .
Denetiminizin farklı temaları desteklemesini istiyorsunuz.
FrameworkElement 'ten türetme
UserControlVar olan öğeleri oluşturma işleminden türetilen veya bunları temel alan denetimler Control . Birçok senaryoda, ' den devralan herhangi bir nesne bir içinde olabileceğinden, bu, kabul edilebilir bir çözümdür FrameworkElementControlTemplate . Ancak, bir denetimin görünümü basit öğe kompozisyonunun işlevlerinden daha fazlasını gerektirdiğinde zaman vardır. Bu senaryolar için, bir bileşeni temel alan FrameworkElement doğru tercih edilir.
Yapı tabanlı bileşenler için iki standart yöntem vardır FrameworkElement : doğrudan işleme ve özel öğe oluşturma. Doğrudan işleme yöntemi geçersiz kılmayı OnRenderFrameworkElement ve DrawingContext bileşen görsellerini açıkça tanımlayan işlemleri sağlamayı içerir. Bu, ve tarafından kullanılan yöntemidir ImageBorder . Özel öğe kompozisyonu Visual , bileşeninizin görünümünü oluşturmak için türündeki nesnelerin kullanımını içerir. Bir örnek için bkz. DrawingVisual nesnelerini kullanma. Track , WPF 'de özel öğe kompozisyonu kullanan bir denetimin örneğidir. Aynı denetimde doğrudan işleme ve özel öğe oluşturmayı karıştırmak da mümkündür.
FrameworkElement 'ten Türetmenin avantajları
Aşağıdakilerden birini uyguladığınızda ' den türetmeyi göz önünde bulundurun FrameworkElement :
Denetimin görünümü üzerinde basit öğe kompozisyonu tarafından sağlananların ötesinde kesin denetim sahibi olmak istiyorsunuz.
Kendi oluşturma mantığınızı tanımlayarak denetiminizin görünümünü tanımlamak istiyorsunuz.
Ve ile mümkün olan unsurların ötesine geçen önemli yollarla mevcut öğeleri oluşturmak istersiniz UserControlControl .
Denetim Yazma Temelleri
Daha önce anlatıldığı gibi, WPF 'nin en güçlü özelliklerinden biri de bir denetimin temel özelliklerinin, görünümünü ve davranışını değiştirmek, ancak yine de özel bir denetim oluşturmaya gerek yoktur. Stil, veri bağlama ve tetikleyici özellikleri WPF özellik sistemi ve WPF olay sistemi tarafından mümkün hale getirilir. Aşağıdaki bölümlerde, özel denetim oluşturmak için kullandığınız modelden bağımsız olarak, özel denetiminizin kullanıcıları bu özellikleri WPF 'e dahil ettikleri gibi kullanabilmeniz için, izlemeniz gereken bazı yöntemler açıklanır.
Bağımlılık özelliklerini kullanma
Bir özellik bir bağımlılık özelliği olduğunda, şunları yapmak mümkündür:
Bir stilde özelliği ayarlayın.
Özelliği bir veri kaynağına bağlayın.
Özelliğin değeri olarak dinamik bir kaynak kullanın.
Özelliği canlandırın.
Denetiminizin bir özelliğinin bu işlevlerden herhangi birini desteklemesini istiyorsanız, bunu bir bağımlılık özelliği olarak uygulamalısınız. Aşağıdaki örnek, aşağıdaki işlemleri gerçekleştirerek adlı bir bağımlılık özelliğini tanımlar Value :
DependencyPropertyAlan olarak adlandırılan bir tanımlayıcı tanımlayın
ValuePropertypublicstaticreadonly.Aşağıdaki belirtmek için, özellik adını çağırarak özellik sistemiyle kaydedin DependencyProperty.Register :
Özelliğin adı.
Özelliğin türü.
Özelliğin sahibi olan tür.
Özelliğin meta verileri. Meta veriler, özelliğinin varsayılan değerini, a ve, içerir CoerceValueCallbackPropertyChangedCallback .
ValueÖzellik ve erişimcileri uygulayarak bağımlılık özelliğini kaydetmek için kullanılan aynı ada sahip adlı BIR clr sarmalayıcı özelliği tanımlayıngetset.getVeseterişimcilerinin yalnızca ve sırasıyla çağrı olduğunu unutmayın GetValueSetValue . İstemciler ve WPF erişimcileri ve çağrıyı atlayabildiğinden ve doğrudan çağırabileceğinden, bağımlılık özellikleri erişimcilerinin ek mantık içermemesi önerilir GetValueSetValue . Örneğin, bir özellik bir veri kaynağına bağlandığında, özelliğinseterişimcisi çağrılmaz. Get ve set erişimcilerine ek mantık eklemek yerine,,,, ve ' ı, ValidateValueCallbackCoerceValueCallbackPropertyChangedCallback değiştiğinde değerini yanıtlamak veya denetlemek için kullanın. Bu geri çağrılar hakkında daha fazla bilgi için bkz. bağımlılık özelliği geri çağırmaları ve doğrulama.Adlandırılmış için bir yöntem tanımlayın CoerceValueCallback
CoerceValue.CoerceValueBunun dahaValuebüyük veya eşit ya daMinValuedaha küçük veya eşit olmasını sağlarMaxValue.Adlı için bir yöntem tanımlayın PropertyChangedCallback
OnValueChanged.OnValueChangedbir RoutedPropertyChangedEventArgs<T> nesnesi oluşturur ve yönlendirilmiş olayı yükseltmek için hazırlarValueChanged. Yönlendirilmiş olaylar, sonraki bölümde ele alınmıştır.
/// <summary>
/// Identifies the Value dependency property.
/// </summary>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(MinValue, new PropertyChangedCallback(OnValueChanged),
new CoerceValueCallback(CoerceValue)));
/// <summary>
/// Gets or sets the value assigned to the control.
/// </summary>
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static object CoerceValue(DependencyObject element, object value)
{
decimal newValue = (decimal)value;
NumericUpDown control = (NumericUpDown)element;
newValue = Math.Max(MinValue, Math.Min(MaxValue, newValue));
return newValue;
}
private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
NumericUpDown control = (NumericUpDown)obj;
RoutedPropertyChangedEventArgs<decimal> e = new RoutedPropertyChangedEventArgs<decimal>(
(decimal)args.OldValue, (decimal)args.NewValue, ValueChangedEvent);
control.OnValueChanged(e);
}
''' <summary>
''' Identifies the Value dependency property.
''' </summary>
Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Decimal), GetType(NumericUpDown), New FrameworkPropertyMetadata(MinValue, New PropertyChangedCallback(AddressOf OnValueChanged), New CoerceValueCallback(AddressOf CoerceValue)))
''' <summary>
''' Gets or sets the value assigned to the control.
''' </summary>
Public Property Value() As Decimal
Get
Return CDec(GetValue(ValueProperty))
End Get
Set(ByVal value As Decimal)
SetValue(ValueProperty, value)
End Set
End Property
Private Shared Overloads Function CoerceValue(ByVal element As DependencyObject, ByVal value As Object) As Object
Dim newValue As Decimal = CDec(value)
Dim control As NumericUpDown = CType(element, NumericUpDown)
newValue = Math.Max(MinValue, Math.Min(MaxValue, newValue))
Return newValue
End Function
Private Shared Sub OnValueChanged(ByVal obj As DependencyObject, ByVal args As DependencyPropertyChangedEventArgs)
Dim control As NumericUpDown = CType(obj, NumericUpDown)
Dim e As New RoutedPropertyChangedEventArgs(Of Decimal)(CDec(args.OldValue), CDec(args.NewValue), ValueChangedEvent)
control.OnValueChanged(e)
End Sub
Daha fazla bilgi için bkz. Özel bağımlılık özellikleri.
Yönlendirilmiş olayları kullanma
Bağımlılık özellikleri, CLR özelliklerinin kavramını ek işlevlerle genişletmenin yanı da, yönlendirilmiş olaylar standart CLR olayları kavramını uzatır. Yeni bir WPF denetimi oluşturduğunuzda, yönlendirilmiş bir olay aşağıdaki davranışı desteklediğinden, olayınızı yönlendirilmiş bir olay olarak uygulamak da iyi bir uygulamadır:
Olaylar, birden fazla denetimin üst öğesi üzerinde işlenebilir. Bir olay bir kabarcıklanma olayıdır, öğe ağacındaki tek bir üst öğe olaya abone olabilir. Ardından, uygulama yazarları birden çok denetimin olayına yanıt vermek için bir işleyici kullanabilir. Örneğin, denetiminiz bir içindeki her öğenin parçasıysa ListBox (bir ' a dahil edildiği için DataTemplate ), uygulama geliştiricisi, denetim olayınızın ' de olay işleyicisini tanımlayabilir ListBox . Her bir denetim üzerinde olay gerçekleştiğinde olay işleyicisi çağırılır.
Yönlendirilmiş olaylar EventSetter , uygulama geliştiricilerinin bir stil içindeki bir olayın işleyicisini belirtmesini sağlayan bir ' de kullanılabilir.
Yönlendirilmiş olaylar EventTrigger , XAML kullanarak özellikleri hareketlendirmek için yararlı olan bir içinde kullanılabilir. Daha fazla bilgi için bkz. animasyon genel bakış.
Aşağıdaki örnek aşağıdakileri yaparak bir yönlendirilmiş olayı tanımlar:
RoutedEventAlan olarak adlandırılan bir tanımlayıcı tanımlayın
ValueChangedEventpublicstaticreadonly.Yöntemini çağırarak yönlendirilmiş olayı kaydedin EventManager.RegisterRoutedEvent . Örnek, çağrı sırasında aşağıdaki bilgileri belirtir RegisterRoutedEvent :
Olayın adı
ValueChanged.Yönlendirme stratejisi, Bubble kaynak üzerindeki bir olay işleyicisinin (olayı oluşturan nesne) ilk olarak çağrıldığı ve ardından kaynağın üst öğelerinde olay işleyicilerinin, en yakın üst öğedeki olay işleyicisiyle başlayarak birbirini izleyen şekilde çağrıldığı anlamına gelir.
Olay işleyicisinin türü RoutedPropertyChangedEventHandler<T> , bir tür ile oluşturulur Decimal .
Olayın sahibi olan türü
NumericUpDown.
Adlı bir genel olay bildirin
ValueChangedve olay erişimcisi bildirimlerini içerir. Örnek, AddHandleraddRemoveHandlerremoveWPF olay hizmetlerini kullanmak için erişimci bildiriminde ve erişimci bildiriminde çağırır.Olayı oluşturan adlı korumalı, sanal bir yöntem oluşturun
OnValueChangedValueChanged.
/// <summary>
/// Identifies the ValueChanged routed event.
/// </summary>
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
"ValueChanged", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<decimal>), typeof(NumericUpDown));
/// <summary>
/// Occurs when the Value property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
/// <summary>
/// Raises the ValueChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.</param>
protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs<decimal> args)
{
RaiseEvent(args);
}
''' <summary>
''' Identifies the ValueChanged routed event.
''' </summary>
Public Shared ReadOnly ValueChangedEvent As RoutedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, GetType(RoutedPropertyChangedEventHandler(Of Decimal)), GetType(NumericUpDown))
''' <summary>
''' Occurs when the Value property changes.
''' </summary>
Public Custom Event ValueChanged As RoutedPropertyChangedEventHandler(Of Decimal)
AddHandler(ByVal value As RoutedPropertyChangedEventHandler(Of Decimal))
MyBase.AddHandler(ValueChangedEvent, value)
End AddHandler
RemoveHandler(ByVal value As RoutedPropertyChangedEventHandler(Of Decimal))
MyBase.RemoveHandler(ValueChangedEvent, value)
End RemoveHandler
RaiseEvent(ByVal sender As System.Object, ByVal e As RoutedPropertyChangedEventArgs(Of Decimal))
End RaiseEvent
End Event
''' <summary>
''' Raises the ValueChanged event.
''' </summary>
''' <param name="args">Arguments associated with the ValueChanged event.</param>
Protected Overridable Sub OnValueChanged(ByVal args As RoutedPropertyChangedEventArgs(Of Decimal))
MyBase.RaiseEvent(args)
End Sub
Daha fazla bilgi için bkz. yönlendirilmiş olaylara genel bakış ve özel bir yönlendirilmiş olay oluşturma.
Bağlamayı kullan
Denetiminizin Kullanıcı arabirimini mantığa ayırmak için veri bağlamayı kullanmayı düşünün. Bu, bir kullanarak denetiminizin görünümünü tanımlarsanız özellikle önemlidir ControlTemplate . Veri bağlamayı kullandığınızda, koddan Kullanıcı arabiriminin belirli bölümlerine başvurma gereksinimini ortadan kaldırabiliyor olabilirsiniz. Kod içinde olan ControlTemplate öğelerin başvurduğu ControlTemplate ve ControlTemplate değiştirildiği, başvurulan öğenin yeni içine dahil olması gerektiği için, içinde bulunan öğelerin başvurmaması iyi bir fikirdir ControlTemplate .
Aşağıdaki örnek, TextBlockNumericUpDown denetimin ' de bir ad atamasını ve koddaki ada göre TextBox 'a başvurmayı sağlar.
<Border BorderThickness="1" BorderBrush="Gray" Margin="2"
Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBlock Name="valueText" Width="60" TextAlignment="Right" Padding="5"/>
</Border>
private void UpdateTextBlock()
{
valueText.Text = Value.ToString();
}
Private Sub UpdateTextBlock()
valueText.Text = Value.ToString()
End Sub
Aşağıdaki örnek, aynı şeyi gerçekleştirmek için bağlamayı kullanır.
<Border BorderThickness="1" BorderBrush="Gray" Margin="2"
Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Stretch">
<!--Bind the TextBlock to the Value property-->
<TextBlock
Width="60" TextAlignment="Right" Padding="5"
Text="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:NumericUpDown}},
Path=Value}"/>
</Border>
Veri bağlama hakkında daha fazla bilgi için bkz. veri bağlamaya genel bakış.
Tasarımcılar için tasarım
Visual Studio için wpf tasarımcısında özel WPF denetimleri için destek almak üzere (örneğin, Özellikler penceresi ile özellik düzenlemesi), bu yönergeleri izleyin. WPF Tasarımcısı için geliştirme hakkında daha fazla bilgi için bkz. VISUAL STUDIO xaml tasarlama.
Bağımlılık Özellikleri
getset Daha önce AÇıKLANDıĞı gibi CLR ve erişimcileri, "bağımlılık özelliklerini kullan" bölümünde uyguladığınızdan emin olun. Tasarımcılar bir bağımlılık özelliğinin varlığını algılamak için sarmalayıcı kullanabilir, ancak WPF ve denetimin istemcileri gibi, özelliği alırken veya ayarlarken erişimcileri çağırmak için gerekli değildir.
İliştirilmiş Özellikler
Aşağıdaki yönergeleri kullanarak özel denetimlere Ekli Özellikler uygulamalısınız:
publicstaticreadonlyDependencyProperty Yöntemi kullanılarak oluşturulan bir formpublic'e sahipPropertyRegisterAttached . Geçirilen Özellik adı RegisterAttachedRegisterAttachedile aynı olmalıdır.publicstaticSetpublicveGetstaticadlı bir çift CLR yöntemi uygulayın. Her iki yöntem de DependencyProperty ilk bağımsız değişkeni olarak sınıfından türetilmiş bir sınıfı kabul etmelidir.SetSetyöntemi, türü özelliği için kayıtlı veri türüyle eşleşen bir bağımsız değişkeni de kabul eder.GetGetyöntemi aynı türde bir değer döndürmelidir.SetSetyöntemi eksikse, özelliği salt okunurdur olarak işaretlenir.SetSetveGetGet, GetValueSetValue sırasıyla hedef bağımlılık nesnesi üzerindeki ve yöntemlerine doğrudan yönlendirmelidir. Tasarımcılar, yöntem sarmalayıcısı aracılığıyla arayarak veya hedef bağımlılık nesnesine doğrudan çağrı yaparak ekli özelliğe erişebilir.
Ekli Özellikler hakkında daha fazla bilgi için bkz. ekli özelliklere genel bakış.
Paylaşılan kaynakları tanımlama ve kullanma
Denetiminizi uygulamanız ile aynı derlemeye dahil edebilir veya birden çok uygulamada kullanılabilen ayrı bir derlemede denetiminizi paketleyebilir. Çoğu bölümde, bu konuda tartışılan bilgiler kullandığınız yöntemden bağımsız olarak geçerlidir. Ancak, buna dikkat edilecek bir fark vardır. Bir uygulamayı bir uygulama olarak aynı derlemeye yerleştirdiğinizde, App. xaml dosyasına genel kaynaklar ekleyebilirsiniz. Ancak yalnızca denetimleri içeren bir derlemeye Application kendisiyle ilişkili bir nesne yoktur, bu nedenle App. xaml dosyası kullanılamaz.
Bir uygulama bir kaynağı ararken, üç düzeye aşağıdaki sırayla bakar:
Öğe düzeyi.
Sistem, kaynağa başvuruda bulunan öğeyle başlar ve sonra mantıksal üst öğenin kaynaklarını arar ve bu nedenle kök öğeye ulaşılana kadar bu şekilde devam eder.
Uygulama düzeyi.
Nesne tarafından tanımlanan kaynaklar Application .
Tema düzeyi.
Tema düzeyi sözlükler, Temalar adlı bir alt klasörde depolanır. Temalar klasöründeki dosyalar temalara karşılık gelir. Örneğin, Aero. NormalColor. xaml, Luna. NormalColor. xaml, Royale. NormalColor. xaml, vb. olabilir. Ayrıca, Generic. xaml adlı bir dosyaya da sahip olabilirsiniz. Sistem Temalar düzeyinde bir kaynak ararken, önce temaya özel dosyada arama yapar ve ardından bunu genel. xaml içinde arar.
Denetiminiz uygulamadan ayrı bir derlemede olduğunda, genel kaynaklarınızı öğe düzeyinde veya tema düzeyinde koymanız gerekir. Her iki yöntem de avantajlarına sahiptir.
Öğe düzeyinde kaynakları tanımlama
Özel bir kaynak sözlüğü oluşturarak ve denetimin kaynak sözlüğü ile birleştirerek, öğe düzeyinde paylaşılan kaynaklar tanımlayabilirsiniz. Bu yöntemi kullandığınızda, kaynak dosyanıza istediğiniz her şeyi verebilir ve denetimleriniz ile aynı klasörde olabilir. Öğe düzeyindeki kaynaklar, anahtar olarak basit dizeler da kullanabilir. Aşağıdaki örnek LinearGradientBrush Dictionary1. xaml adlı bir kaynak dosyası oluşturur.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush
x:Key="myBrush"
StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
</LinearGradientBrush>
</ResourceDictionary>
Sözlüğünüzü tanımladıktan sonra denetimin kaynak sözlüğü ile birleştirmeniz gerekir. Bunu XAML veya kod kullanarak yapabilirsiniz.
Aşağıdaki örnek, XAML kullanarak bir kaynak sözlüğünü birleştirir.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Bu yaklaşımın dezavantajı, ResourceDictionary ona her başvurduğunuzda bir nesne oluşturulur. Örneğin, kitaplığınızda 10 özel denetiminiz varsa ve XAML kullanarak her denetim için paylaşılan kaynak sözlüklerini birleştirirseniz, 10 özdeş ResourceDictionary nesne oluşturursunuz. Bu, koddaki kaynakları birleştiren ve sonucu döndüren bir statik sınıf oluşturarak bunu önleyebilirsiniz ResourceDictionary .
Aşağıdaki örnek, paylaşılan bir sınıf oluşturur ResourceDictionary .
internal static class SharedDictionaryManager
{
internal static ResourceDictionary SharedDictionary
{
get
{
if (_sharedDictionary == null)
{
System.Uri resourceLocater =
new System.Uri("/ElementResourcesCustomControlLibrary;component/Dictionary1.xaml",
System.UriKind.Relative);
_sharedDictionary =
(ResourceDictionary)Application.LoadComponent(resourceLocater);
}
return _sharedDictionary;
}
}
private static ResourceDictionary _sharedDictionary;
}
Aşağıdaki örnek, bir paylaşılan kaynağı, çağrı yapmadan önce denetimin oluşturucusunda özel bir denetimin kaynaklarıyla birleştirir InitializeComponent . SharedDictionaryManager.SharedDictionaryStatik bir özellik olduğundan, ResourceDictionary yalnızca bir kez oluşturulur. Kaynak sözlüğü çağrılmadan önce birleştirildiğinden InitializeComponent , kaynaklar xaml dosyasında denetim için kullanılabilir.
public NumericUpDown()
{
this.Resources.MergedDictionaries.Add(SharedDictionaryManager.SharedDictionary);
InitializeComponent();
}
Tema düzeyinde kaynakları tanımlama
WPF, farklı Windows temaları için kaynaklar oluşturmanızı sağlar. Denetim yazarı olarak, belirli bir temaya ait bir kaynağı tanımlayabilir ve hangi temanın kullanımda olduğuna bağlı olarak denetiminizin görünümünü değiştirebilirsiniz. örneğin, Button Windows klasik temadaki görünümü (Windows 2000 için varsayılan tema) Button , ButtonControlTemplate her tema için farklı bir değer kullandığından Windows Luna temasının (Windows XP için varsayılan tema) bir ' dan farklıdır.
Bir temaya özgü kaynaklar, belirli bir dosya adına sahip bir kaynak sözlüğünde tutulur. Bu dosyalar, Themes denetimi içeren klasörün bir alt klasörü olan adlı bir klasörde olmalıdır. Aşağıdaki tabloda, kaynak sözlüğü dosyaları ve her bir dosyayla ilişkili tema listelenmektedir:
| Kaynak sözlüğü dosya adı | Windows teması |
|---|---|
Classic.xaml |
klasik Windows 9x/2000 Windows XP 'ye bakma |
Luna.NormalColor.xaml |
Windows XP 'de varsayılan mavi tema |
Luna.Homestead.xaml |
Windows XP 'de zeytin teması |
Luna.Metallic.xaml |
Windows XP 'de gümüş teması |
Royale.NormalColor.xaml |
Windows XP Media Center Edition 'da varsayılan tema |
Aero.NormalColor.xaml |
Windows Vista 'da varsayılan tema |
Her tema için bir kaynak tanımlamanız gerekmez. Belirli bir tema için bir kaynak tanımlanmamışsa denetim, Classic.xaml kaynağı denetler. Kaynak, geçerli temaya veya ' de karşılık gelen dosyada tanımlanmamışsa, Classic.xaml Denetim adlı bir kaynak sözlüğü dosyasında olan genel kaynağı kullanır generic.xaml . generic.xamlDosya, temaya özgü kaynak sözlüğü dosyalarıyla aynı klasörde bulunur. generic.xaml, belirli bir Windows temaya karşılık gelmese de, hala tema düzeyi bir sözlüktür.
C# veya Visual Basic NumericUpDown özel denetimi ile tema ve uı otomasyonu desteği örneği, denetim için iki kaynak sözlüğü içerir : biri generic. xaml içinde, diğeri de Luna. normalcolor. xaml ' de bulunur.
ControlTemplateTemayı özel kaynak sözlüğü dosyalarından birine yerleştirdiğinizde, denetiminiz için bir statik oluşturucu oluşturmanız ve OverrideMetadata(Type, PropertyMetadata)DefaultStyleKey Aşağıdaki örnekte gösterildiği gibi, üzerinde yöntemini çağırmanız gerekir.
static NumericUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown),
new FrameworkPropertyMetadata(typeof(NumericUpDown)));
}
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(NumericUpDown), New FrameworkPropertyMetadata(GetType(NumericUpDown)))
End Sub
Tema kaynakları için anahtar tanımlama ve başvuru
Öğe düzeyinde bir kaynak tanımladığınızda, anahtarı olarak bir dize atayabilir ve dize aracılığıyla kaynağa erişebilirsiniz. Tema düzeyinde bir kaynak tanımladığınızda, ComponentResourceKey anahtar olarak bir olarak kullanmanız gerekir. Aşağıdaki örnek, genel. xaml içinde bir kaynağı tanımlar.
<LinearGradientBrush
x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:Painter},
ResourceId=MyEllipseBrush}"
StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="Red" Offset="0.5" />
<GradientStop Color="Green" Offset="1"/>
</LinearGradientBrush>
Aşağıdaki örnek, anahtar olarak öğesini belirterek kaynağa başvurur ComponentResourceKey .
<RepeatButton
Grid.Column="1" Grid.Row="0"
Background="{StaticResource {ComponentResourceKey
TypeInTargetAssembly={x:Type local:NumericUpDown},
ResourceId=ButtonBrush}}">
Up
</RepeatButton>
<RepeatButton
Grid.Column="1" Grid.Row="1"
Background="{StaticResource {ComponentResourceKey
TypeInTargetAssembly={x:Type local:NumericUpDown},
ResourceId=ButtonBrush}}">
Down
</RepeatButton>
Tema kaynaklarının konumunu belirtme
Bir denetimin kaynaklarını bulmak için barındırma uygulamasının, derlemenin denetime özgü kaynakları içerdiğini bilmeleri gerekir. Bunu, ThemeInfoAttribute denetimini içeren derlemeye ekleyerek yapabilirsiniz. , ThemeInfoAttributeGenericDictionaryLocation Genel kaynakların konumunu ve ThemeDictionaryLocation temaya özgü kaynakların konumunu belirten bir özelliği olan bir özelliğine sahiptir.
Aşağıdaki örnek, GenericDictionaryLocation ve ThemeDictionaryLocation özelliklerini SourceAssembly , genel ve temaya özgü kaynakların denetimle aynı derlemede olduğunu belirtmek için olarak ayarlar.
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly,
ResourceDictionaryLocation.SourceAssembly)]
<Assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)>