Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Burada C++, C# veya Visual Basic kullanarak bir Windows Çalışma Zamanı uygulaması için kendi bağımlılık özelliklerinizi tanımlamayı ve uygulamayı açıklayacağız. Uygulama geliştiricilerinin ve bileşen yazarlarının özel bağımlılık özellikleri oluşturmak isteme nedenlerini listeledik. Özel bağımlılık özelliği için uygulama adımlarını ve bağımlılık özelliğinin performansını, kullanılabilirliğini veya çok yönlülüğünü geliştirebilecek bazı en iyi yöntemleri açıklıyoruz.
Önkoşullar
Bağımlılık özelliklerine genel bakışını okuduğunuz ve bağımlılık özelliklerini mevcut bağımlılık özelliklerinin tüketicisi açısından anladığınız varsayılır. Bu konudaki örnekleri izlemek için XAML'yi de anlamanız ve C++, C# veya Visual Basic kullanarak temel bir Windows Çalışma Zamanı uygulaması yazmayı bilmeniz gerekir.
Bağımlılık özelliği nedir?
Bir özellik için stil, veri bağlama, animasyonlar ve varsayılan değerleri desteklemek için bağımlılık özelliği olarak uygulanmalıdır. Bağımlılık özelliği değerleri sınıfında alan olarak depolanmaz, xaml çerçevesi tarafından depolanır ve DependencyProperty.Register yöntemi çağrılarak özellik Windows Çalışma Zamanı özellik sistemine kaydedildiğinde alınan bir anahtar kullanılarak başvurulur. Bağımlılık özellikleri yalnızca DependencyObject'ten türetilen türler tarafından kullanılabilir. Ancak Sınıf hiyerarşisinde DependencyObject oldukça yüksektir, bu nedenle kullanıcı arabirimi ve sunu desteğine yönelik sınıfların çoğu bağımlılık özelliklerini destekleyebilir. Bağımlılık özellikleri ve bunları tanımlamak için kullanılan terim ve kuralların bazıları hakkında daha fazla bilgi için bkz . Bağımlılık özelliklerine genel bakış.
Windows Çalışma Zamanı'ndaki bağımlılık özelliklerine örnek olarak şunlar verilebilir: Control.Background, FrameworkElement.Width ve TextBox.Text.
Konvansiyon, bir sınıf tarafından sunulan her bağımlılık özelliğinin, aynı sınıfta bulunan ve bağımlılık özelliği için tanımlayıcı sağlayan, public static readonly türünde karşılık gelen bir DependencyProperty özelliğine sahip olmasıdır. Tanımlayıcının adı şu kurala uyar: bağımlılık özelliğinin adı ve adın sonuna "Özellik" dizesi eklenir. Örneğin, Control.Background özelliği için ilgili DependencyProperty tanımlayıcısı Control.BackgroundProperty'dir. Tanımlayıcı, bağımlılık özelliği hakkındaki bilgileri kaydedildiği gibi depolar ve daha sonra SetValue çağrısı gibi bağımlılık özelliğiyle ilgili diğer işlemler için kullanılabilir.
Özellik sarmalayıcıları
Bağımlılık özellikleri genellikle bir sarmalayıcı uygulamasına sahiptir. Sarmalayıcı olmadan, özellikleri alma veya ayarlamanın tek yolu GetValue ve SetValue bağımlılık özelliği yardımcı programı yöntemlerini kullanmak ve tanımlayıcıyı bunlara parametre olarak geçirmektir. Bu, normalde bir özellik olan bir şey için oldukça doğal olmayan bir kullanımdır. Ancak sarmalayıcı ile kodunuz ve bağımlılık özelliğine başvuran diğer tüm kodlar, kullandığınız dil için doğal olan basit bir nesne özelliği söz dizimi kullanabilir.
Özel bağımlılık özelliğini kendiniz uygularsanız ve bunun genel ve çağrılabilmesini istiyorsanız, özellik sarmalayıcılarını da tanımlayın. Özellik sarmalayıcıları, bağımlılık özelliği hakkındaki temel bilgileri yansıma veya statik analiz işlemlerine raporlamak için de yararlıdır. Özellikle, sarmalayıcı ContentPropertyAttribute gibi öznitelikleri yerleştirdiğiniz yerdir.
Bir özellik bağımlılık özelliği olarak ne zaman uygulanır?
Sınıfınız DependencyObject'ten türetdiği sürece bir sınıfa genel okuma/yazma özelliği uyguladığınızda, özelliğinizin bağımlılık özelliği olarak çalışmasını sağlama seçeneğiniz vardır. Bazen özelliğinizi özel bir alanla yedeklemenin tipik tekniği yeterli olur. Özel özelliğinizi bağımlılık özelliği olarak tanımlamak her zaman gerekli veya uygun değildir. Seçim, mülkünüzün desteklemesini istediğiniz senaryolara bağlı olacaktır.
Windows Çalışma Zamanı veya Windows Çalışma Zamanı uygulamalarının şu özelliklerinden birini veya daha fazlasını desteklemesini istediğinizde, özelliğinizi bağımlılık özelliği olarak uygulamayı düşünebilirsiniz:
- Özelliği bir Stil aracılığıyla ayarlama
- {Binding} ile veri bağlamada geçerli bir hedef özellik olarak işlev görme
- Storyboard aracılığıyla animasyonlu değerleri destekleme
- Özelliğin değeri değiştirildiğinde raporlama:
- Mülk sistemi tarafından otomatik olarak yapılan eylemler
- Ortam
- Kullanıcı eylemleri
- Okuma ve yazma stilleri
Bağımlılık özelliği tanımlamak için denetim listesi
Bağımlılık özelliğinin tanımlanması bir kavram kümesi olarak düşünülebilir. Çeşitli kavramlar uygulamadaki tek bir kod satırında ele alınabildiğinden, bu kavramlar yordamsal adımlar olmayabilir. Bu liste yalnızca hızlı bir genel bakış sağlar. Bu konunun ilerleyen bölümlerinde her kavramı daha ayrıntılı olarak açıklayacağız ve size örnek kodu çeşitli dillerde göstereceğiz.
- Sahip türünü ve özellik değerinin türünü belirterek özellik adını özellik sistemine kaydedin ( Register'ı çağırın).
- Register için özellik meta verilerini bekleyen gerekli bir parametre vardır. Bunun için null değerini belirtin veya özellik değiştirme davranışını veya ClearValue çağrılarak geri yüklenebilen meta veri tabanlı bir varsayılan değer istiyorsanız PropertyMetadata örneğini belirtin.
- Sahip türünde bir DependencyProperty tanımlayıcısını genel statik salt okunur özellik üyesi olarak tanımlayın.
- Uyguladığınız dilde kullanılan özellik erişimcisi modelini izleyerek bir sarmalayıcı özelliği tanımlayın. Sarmalayıcı özellik adı, Register'da kullandığınız ad dizesiyle eşleşmelidir. GetValue ve SetValue çağrısı yaparak ve kendi özelliğinizin tanımlayıcısını parametre olarak geçirerek sarmalayıcıyı sarmaladığı bağımlılık özelliğine bağlamak için get ve set erişimcilerini uygulayın.
- (İsteğe bağlı) ContentPropertyAttribute gibi öznitelikleri sarmalayıcıya yerleştirin.
Uyarı
Özel bir ekli özellik tanımladığınızda, genellikle sarmalayıcıyı atlıyorsunuz. Bunun yerine, bir XAML işlemcisinin kullanabileceği farklı bir erişimci stili yazarsınız. Bkz. Özel ekli özellikler.
Özelliği kaydetme
Özelliğinizin bağımlılık özelliği olması için, özelliği Windows Çalışma Zamanı özellik sistemi tarafından tutulan bir özellik deposuna kaydetmeniz gerekir. Özelliğini kaydetmek için Register yöntemini çağırırsınız.
Microsoft .NET dilleri (C# ve Microsoft Visual Basic) için, sınıfınızın gövdesinde (sınıfın içinde, ancak üye tanımlarının dışında) Register'ı çağırırsınız. Tanımlayıcı, dönüş değeri olarak Register yöntemi çağrısı tarafından sağlanır. Register çağrısı genellikle statik bir oluşturucu olarak veya sınıfınızın bir parçası olarak DependencyProperty türünde genel statik salt okunur özelliğinin başlatılmasının bir parçası olarak yapılır. Bu özellik bağımlılık özelliğinizin tanımlayıcısını kullanıma sunar. Aşağıda Register çağrısı örnekleri verilmiştir.
Uyarı
Bağımlılık özelliğini tanımlayıcı özellik tanımının bir parçası olarak kaydetmek tipik bir uygulamadır, ancak sınıf statik oluşturucusunda bir bağımlılık özelliğini de kaydedebilirsiniz. Bağımlılık özelliğini başlatmak için birden fazla kod satırına ihtiyacınız varsa bu yaklaşım mantıklı olabilir.
C++/CX için, uygulamayı üst bilgiyle kod dosyası arasında bölme seçenekleriniz vardır. tr-TR: Tipik bölme, tanımlayıcının kendisinin başlıkta genel statik özellik olarak bildirilmesi ve get uygulaması ile birlikte set olmadan olmasıdır. Get uygulaması, başlatılmamış bir DependencyProperty örneği olan özel bir alana başvurur. Sarmalayıcıları ve sarmalayıcının get ve set uygulamalarını da bildirebilirsiniz. Bu durumda üst bilgi, minimal bir uygulama içerir. Sarmalayıcının Windows Çalışma Zamanı ilişkilendirmesi gerekiyorsa, üst bilgiye de bu ilişkilendirmeyi ekleyin. Yazmaç çağrısını kod dosyasına, yalnızca uygulama ilk kez başlatıldığında çalıştırılacak bir yardımcı işlevin içine yerleştirin. Uygulama dosyasının kök kapsamındaki başlıkta bildirdiğiniz, statik fakat başlatılmamış Register tanımlayıcılarını doldurmak için nullptr dönüş değerini kullanın.
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
nameof(Label),
typeof(String),
typeof(ImageWithLabelControl),
new PropertyMetadata(null)
);
Public Shared ReadOnly LabelProperty As DependencyProperty =
DependencyProperty.Register("Label",
GetType(String),
GetType(ImageWithLabelControl),
New PropertyMetadata(Nothing))
// ImageWithLabelControl.idl
namespace ImageWithLabelControlApp
{
runtimeclass ImageWithLabelControl : Windows.UI.Xaml.Controls.Control
{
ImageWithLabelControl();
static Windows.UI.Xaml.DependencyProperty LabelProperty{ get; };
String Label;
}
}
// ImageWithLabelControl.h
...
struct ImageWithLabelControl : ImageWithLabelControlT<ImageWithLabelControl>
{
...
public:
static Windows::UI::Xaml::DependencyProperty LabelProperty()
{
return m_labelProperty;
}
private:
static Windows::UI::Xaml::DependencyProperty m_labelProperty;
...
};
// ImageWithLabelControl.cpp
...
Windows::UI::Xaml::DependencyProperty ImageWithLabelControl::m_labelProperty =
Windows::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<ImageWithLabelControlApp::ImageWithLabelControl>(),
Windows::UI::Xaml::PropertyMetadata{ nullptr }
);
...
//.h file
//using namespace Windows::UI::Xaml::Controls;
//using namespace Windows::UI::Xaml::Interop;
//using namespace Windows::UI::Xaml;
//using namespace Platform;
public ref class ImageWithLabelControl sealed : public Control
{
private:
static DependencyProperty^ _LabelProperty;
...
public:
static void RegisterDependencyProperties();
static property DependencyProperty^ LabelProperty
{
DependencyProperty^ get() {return _LabelProperty;}
}
...
};
//.cpp file
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml.Interop;
DependencyProperty^ ImageWithLabelControl::_LabelProperty = nullptr;
// This function is called from the App constructor in App.xaml.cpp
// to register the properties
void ImageWithLabelControl::RegisterDependencyProperties()
{
if (_LabelProperty == nullptr)
{
_LabelProperty = DependencyProperty::Register(
"Label", Platform::String::typeid, ImageWithLabelControl::typeid, nullptr);
}
}
Uyarı
C++/CX kodu için, DependencyProperty'yi ortaya çıkaran özel bir alanınızın ve genel salt okunur özelliğinizin olmasının nedeni, bağımlılık özelliğinizi kullanan diğer çağıranların da tanımlayıcının genel olmasını gerektiren özellik sistemi yardımcı programı API'lerini kullanabilmeleridir. Tanımlayıcıyı gizli tutarsanız, kişiler bu yardımcı program API'lerini kullanamaz. Bu tür API ve senaryolara örnek olarak GetValue veya SetValue by choice, ClearValue, GetAnimationBaseValue, SetBinding ve Setter.Property verilebilir. Windows Çalışma Zamanı meta veri kuralları ortak alanlara izin vermediğinden, bunun için ortak alan kullanamazsınız.
Bağımlılık özelliği adı kuralları
Bağımlılık özellikleri için adlandırma kuralları vardır; istisnai durumlar dışında onları takip edin. Bağımlılık özelliği, Register'ın ilk parametresi olarak verilen "Etiket" gibi temel bir ad taşır. Adın her kayıt türü içinde benzersiz olması gerekir ve benzersizlik gereksinimi devralınan üyeler için de geçerlidir. Temel türler aracılığıyla devralınan bağımlılık özellikleri zaten kayıt türünün parçası olarak kabul edilir; devralınan özelliklerin adları yeniden kaydedilemez.
Uyarı
Burada sağladığınız ad, seçtiğiniz dil için programlamada geçerli olan herhangi bir dize tanımlayıcısı olsa da, genellikle XAML'de bağımlılık özelliğinizi de ayarlamak istersiniz. XAML'de ayarlanabilmesi için seçtiğiniz özellik adının geçerli bir XAML adı olması gerekir. Daha fazla bilgi için bkz . XAML'ye genel bakış.
Tanımlayıcı özelliğini oluştururken, özelliği kaydettiğiniz adla birlikte "Özellik" sonekiyle birleştirin (örneğin, "LabelProperty"). Bu özellik bağımlılık özelliği için tanımlayıcınızdır ve kendi özellik sarmalayıcılarınızda yaptığınız SetValue ve GetValue çağrıları için giriş olarak kullanılır. Ayrıca özellik sistemi ve {x:Bind} gibi diğer XAML işlemcileri tarafından da kullanılır
Sarmalayıcıyı uygulama
Özellik sarmalayıcınız, get uygulamasında GetValue ve set uygulamasında SetValue çağrısı yapmalıdır.
Uyarı
Olağanüstü durumlar dışında, sarmalayıcı uygulamalarınız yalnızca GetValue ve SetValue işlemlerini gerçekleştirmelidir. Aksi takdirde, özelliğiniz XAML aracılığıyla ayarlandığında ve kod aracılığıyla ayarlandığında farklı davranışlar elde edersiniz. Verimlilik için XAML ayrıştırıcısı bağımlılık özelliklerini ayarlarken sarmalayıcıları atlar; ve SetValue aracılığıyla yedekleme deposuyla konuşur.
public String Label
{
get { return (String)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
Public Property Label() As String
Get
Return DirectCast(GetValue(LabelProperty), String)
End Get
Set(ByVal value As String)
SetValue(LabelProperty, value)
End Set
End Property
// ImageWithLabelControl.h
...
winrt::hstring Label()
{
return winrt::unbox_value<winrt::hstring>(GetValue(m_labelProperty));
}
void Label(winrt::hstring const& value)
{
SetValue(m_labelProperty, winrt::box_value(value));
}
...
//using namespace Platform;
public:
...
property String^ Label
{
String^ get() {
return (String^)GetValue(LabelProperty);
}
void set(String^ value) {
SetValue(LabelProperty, value);
}
}
Özel bağımlılık özelliği için özellik meta verileri
Özellik meta verileri bir bağımlılık özelliğine atandığında, özellik sahibi türünün veya alt sınıflarının her örneği için bu özelliğe aynı meta veriler uygulanır. Özellik meta verilerinde iki davranış belirtebilirsiniz:
- Özellik sisteminin özelliğin tüm örneklerinde atadığı varsayılan değerdir.
- Özellik değeri değişikliği algılandığında özellik sisteminde otomatik olarak çağrılan statik geri çağırma yöntemi.
Özellik meta verileriyle Kayıt'ı çağırma
DependencyProperty.Register çağrısının önceki örneklerinde propertyMetadata parametresi için null bir değer geçtik. Bir bağımlılık özelliğini varsayılan değer sağlamak veya özellik tarafından değiştirilen bir geri çağırma kullanmak üzere etkinleştirmek için, bu özelliklerden birini veya her ikisini de sağlayan bir PropertyMetadata örneği tanımlamanız gerekir.
Genellikle, DependencyProperty.Register parametrelerinin içinde satır içi olarak oluşturulmuş bir PropertyMetadata örneği sağlarsınız.
Uyarı
CreateDefaultValueCallback uygulaması tanımlıyorsanız PropertyMetadata örneğini tanımlamak için PropertyMetadata oluşturucuyu çağırmak yerine PropertyMetadata.Create yardımcı programı yöntemini kullanmanız gerekir.
Bu sonraki örnek, PropertyChangedCallback değerine sahip bir PropertyMetadata örneğine başvurarak daha önce gösterilen DependencyProperty.Register örneklerini değiştirir. "OnLabelChanged" geri çağırmasının uygulanması bu bölümün ilerleyen bölümlerinde gösterilecektir.
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
nameof(Label),
typeof(String),
typeof(ImageWithLabelControl),
new PropertyMetadata(null,new PropertyChangedCallback(OnLabelChanged))
);
Public Shared ReadOnly LabelProperty As DependencyProperty =
DependencyProperty.Register("Label",
GetType(String),
GetType(ImageWithLabelControl),
New PropertyMetadata(
Nothing, new PropertyChangedCallback(AddressOf OnLabelChanged)))
// ImageWithLabelControl.cpp
...
Windows::UI::Xaml::DependencyProperty ImageWithLabelControl::m_labelProperty =
Windows::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<ImageWithLabelControlApp::ImageWithLabelControl>(),
Windows::UI::Xaml::PropertyMetadata{ nullptr, Windows::UI::Xaml::PropertyChangedCallback{ &ImageWithLabelControl::OnLabelChanged } }
);
...
DependencyProperty^ ImageWithLabelControl::_LabelProperty =
DependencyProperty::Register("Label",
Platform::String::typeid,
ImageWithLabelControl::typeid,
ref new PropertyMetadata(nullptr,
ref new PropertyChangedCallback(&ImageWithLabelControl::OnLabelChanged))
);
Varsayılan değer
Bir bağımlılık özelliği için varsayılan bir değer belirtebilirsiniz; böylece özellik ayarsız olduğunda her zaman belirli bir varsayılan değer döndürür. Bu değer, bu özelliğin türü için doğal varsayılan değerden farklı olabilir.
Varsayılan bir değer belirtilmezse, bir başvuru türü için bağımlılık özelliğinin varsayılan değeri null, değer türü veya dil ilkel tipi için ise türün varsayılan değeri olur (örneğin, bir tamsayı için 0 veya bir dize için boş bir dize). Varsayılan değer oluşturmanın temel nedeni, özelliğinde ClearValue çağrısı yaptığınızda bu değerin geri yüklenmesidir. Özellik başına bir varsayılan değer oluşturmak, özellikle değer türleri için oluşturucularda varsayılan değerler oluşturmaktan daha kullanışlı olabilir. Ancak, başvuru türleri için varsayılan değer oluşturmanın istenmeyen tekil desen oluşturmadığından emin olun. Daha fazla bilgi için bu konunun devamında yer alan En iyi yöntemler bölümüne bakın
// ImageWithLabelControl.cpp
...
Windows::UI::Xaml::DependencyProperty ImageWithLabelControl::m_labelProperty =
Windows::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<ImageWithLabelControlApp::ImageWithLabelControl>(),
Windows::UI::Xaml::PropertyMetadata{ winrt::box_value(L"default label"), Windows::UI::Xaml::PropertyChangedCallback{ &ImageWithLabelControl::OnLabelChanged } }
);
...
Uyarı
UnsetValue varsayılan değeriyle kaydetmeyin. Bunu yaparsanız, mülk tüketicilerinin kafasını karıştırır ve mülk sisteminde istenmeyen sonuçlar doğuracaktır.
CreateDefaultValueCallback
Bazı senaryolarda, birden fazla ui iş parçacığında kullanılan nesneler için bağımlılık özellikleri tanımlarsınız. Birden çok uygulama tarafından kullanılan bir veri nesnesi veya birden çok uygulamada kullandığınız bir denetim tanımlıyorsanız bu durum söz konusu olabilir. Özelliği kaydeden iş parçacığına bağlı olan varsayılan değer örneği yerine CreateDefaultValueCallback uygulaması sağlayarak nesnenin farklı ui iş parçacıkları arasında değişimini etkinleştirebilirsiniz. Temel olarak CreateDefaultValueCallback varsayılan değerler için bir fabrika tanımlar. CreateDefaultValueCallback tarafından döndürülen değer her zaman nesnesini kullanan geçerli UI CreateDefaultValueCallback iş parçacığıyla ilişkilendirilir.
CreateDefaultValueCallback belirten meta verileri tanımlamak için, bir meta veri örneği döndürmek için PropertyMetadata.Create öğesini çağırmanız gerekir; PropertyMetadata oluşturucularının CreateDefaultValueCallback parametresini içeren bir imzası yoktur.
CreateDefaultValueCallback için tipik uygulama deseni, yeni bir DependencyObject sınıfı oluşturmak, DependencyObject'in her özelliğinin belirli özellik değerini istenen varsayılan değere ayarlamak ve ardından CreateDefaultValueCallback yönteminin dönüş değeri aracılığıyla yeni sınıfı Nesne başvurusu olarak döndürmektir.
Özellik değişikliği geri çağırma yöntemi
Özelliğinizin diğer bağımlılık özellikleriyle etkileşimlerini tanımlamak veya özellik değiştiğinde nesnenizin iç özelliğini veya durumunu güncelleştirmek için özellik tarafından değiştirilen bir geri çağırma yöntemi tanımlayabilirsiniz. Geri arama işleviniz çağrılırsa, özellik sistemi etkin bir özellik değeri değişikliği olduğunu belirlemiştir. Geri çağırma yöntemi statik olduğundan, sınıfın hangi örneğinin değişiklik bildirdiğini bildirdiği için geri çağırmanın d parametresi önemlidir. Tipik bir uygulama, olay verilerinin NewValue özelliğini kullanır ve genellikle d olarak geçirilen nesnede başka bir değişiklik yaparak bu değeri bir şekilde işler. Bir özellik değişikliğine verilen ek yanıtlar NewValue tarafından bildirilen değeri reddetmek, OldValue'yu geri yüklemek veya değeri NewValue'ya uygulanan program kısıtlamasına ayarlamaktır.
Sonraki örnekte PropertyChangedCallback uygulaması gösterilmektedir. Önceki Register örneklerinde başvuruda gördüğünüz yöntemi PropertyMetadata için yapı bağımsız değişkenlerinin bir parçası olarak uygular. Bu geri çağırma tarafından ele alınan senaryo, sınıfın "HasLabelValue" (uygulama gösterilmiyor) adlı hesaplanan salt okunur özelliğine de sahip olmasıdır. "Label" özelliği her yeniden değerlendirildiğinde, bu geri çağırma yöntemi çağrılır ve geri çağırma, bağımlı hesaplanan değerin bağımlılık özelliğindeki değişikliklerle eşitlemede kalmasını sağlar.
private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
ImageWithLabelControl iwlc = d as ImageWithLabelControl; //null checks omitted
String s = e.NewValue as String; //null checks omitted
if (s == String.Empty)
{
iwlc.HasLabelValue = false;
} else {
iwlc.HasLabelValue = true;
}
}
Private Shared Sub OnLabelChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim iwlc As ImageWithLabelControl = CType(d, ImageWithLabelControl) ' null checks omitted
Dim s As String = CType(e.NewValue,String) ' null checks omitted
If s Is String.Empty Then
iwlc.HasLabelValue = False
Else
iwlc.HasLabelValue = True
End If
End Sub
void ImageWithLabelControl::OnLabelChanged(Windows::UI::Xaml::DependencyObject const& d, Windows::UI::Xaml::DependencyPropertyChangedEventArgs const& e)
{
auto iwlc{ d.as<ImageWithLabelControlApp::ImageWithLabelControl>() };
auto s{ winrt::unbox_value<winrt::hstring>(e.NewValue()) };
iwlc.HasLabelValue(s.size() != 0);
}
static void OnLabelChanged(DependencyObject^ d, DependencyPropertyChangedEventArgs^ e)
{
ImageWithLabelControl^ iwlc = (ImageWithLabelControl^)d;
Platform::String^ s = (Platform::String^)(e->NewValue);
if (s->IsEmpty()) {
iwlc->HasLabelValue=false;
}
}
Yapılar ve numaralandırmalar için özellik değişiklik davranışı
DependencyProperty türü bir numaralandırma veya yapıysa, yapının iç değerleri veya numaralandırma değeri değişmese bile geri çağırma çağrılabilir. Bu, yalnızca değer değiştiğinde çağrılan dize gibi bir sistem temel öğesinden farklıdır. Bu, dahili olarak yapılan bu değerler üzerinde kutu ve kutu açma işlemlerinin yan etkisidir. Değerinizin bir numaralandırma veya yapı olduğu bir özellik için PropertyChangedCallback yönteminiz varsa, değerleri kendiniz atayarak ve şimdi türlenen değerler için kullanılabilir olan aşırı yüklenmiş karşılaştırma işleçlerini kullanarak OldValue ve NewValue değerlerini karşılaştırmanız gerekir. Öte yandan, böyle bir işleç yoksa (özel bir yapı için bu durum söz konusu olabilir), tek tek değerleri karşılaştırmanız gerekebilir. Sonuç değerlerin değişmemiş olması durumunda genellikle hiçbir şey yapmamayı seçersiniz.
private static void OnVisibilityValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
if ((Visibility)e.NewValue != (Visibility)e.OldValue)
{
//value really changed, invoke your changed logic here
} // else this was invoked because of boxing, do nothing
}
Private Shared Sub OnVisibilityValueChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
If CType(e.NewValue,Visibility) != CType(e.OldValue,Visibility) Then
' value really changed, invoke your changed logic here
End If
' else this was invoked because of boxing, do nothing
End Sub
static void OnVisibilityValueChanged(Windows::UI::Xaml::DependencyObject const& d, Windows::UI::Xaml::DependencyPropertyChangedEventArgs const& e)
{
auto oldVisibility{ winrt::unbox_value<Windows::UI::Xaml::Visibility>(e.OldValue()) };
auto newVisibility{ winrt::unbox_value<Windows::UI::Xaml::Visibility>(e.NewValue()) };
if (newVisibility != oldVisibility)
{
// The value really changed; invoke your property-changed logic here.
}
// Otherwise, OnVisibilityValueChanged was invoked because of boxing; do nothing.
}
static void OnVisibilityValueChanged(DependencyObject^ d, DependencyPropertyChangedEventArgs^ e)
{
if ((Visibility)e->NewValue != (Visibility)e->OldValue)
{
//value really changed, invoke your changed logic here
}
// else this was invoked because of boxing, do nothing
}
}
En iyi yöntemler
Özel bağımlılık özelliğinizi tanımlarken en iyi yöntemler olarak aşağıdaki noktaları göz önünde bulundurun.
DependencyObject ve iş parçacığı oluşturma
Tüm DependencyObject örnekleri, Bir Windows Çalışma Zamanı uygulaması tarafından gösterilen geçerli Pencere ile ilişkili ui iş parçacığında oluşturulmalıdır. Her DependencyObject ana kullanıcı arabirimi iş parçacığında oluşturulmalıdır, ancak diğer iş parçacıklarından bir dağıtıcı başvurusu kullanılarak, Dispatcher çağrılarak nesnelere erişilebilir.
DependencyObject'in iş parçacığı oluşturma yönleri, genellikle yalnızca ui iş parçacığında çalışan kodun bir bağımlılık özelliğinin değerini değiştirebileceği ve hatta okuyabileceği anlamına geldiği için ilgilidir. İş parçacığı oluşturma sorunları genellikle zaman uyumsuz desenleri ve arka plan çalışan iş parçacıklarını doğru şekilde kullanan tipik kullanıcı arabirimi kodunda önlenebilir. Genellikle dependencyObject ile ilgili iş parçacığı sorunlarıyla yalnızca kendi DependencyObject türlerinizi tanımlıyorsanız ve bunları bir DependencyObject'in uygun olmadığı veri kaynakları veya diğer senaryolar için kullanmayı denediğinizde karşılaşırsınız.
İstenmeyen tekillerden kaçınma
Bir başvuru türü alan bir bağımlılık özelliği bildiriyorsanız ve PropertyMetadata'ınızı oluşturduğunuz kodun bir parçası olarak bu başvuru türü için bir oluşturucu çağırırsanız, istenmeyen bir singleton oluşabilir. Bağımlılık özelliğinin tüm kullanımları yalnızca bir PropertyMetadata örneğini paylaşır ve böylece oluşturduğunuz tek başvuru türünü paylaşmayı dener. Bağımlılık özelliğiniz aracılığıyla ayarladığınız bu değer türünün tüm alt özellikleri, hedeflemediğiniz şekillerde diğer nesnelere yayılır.
Null olmayan bir değer istiyorsanız, başvuru türü bağımlılık özelliği için başlangıç değerlerini ayarlamak için sınıf oluşturucularını kullanabilirsiniz, ancak bunun Bağımlılık özelliklerine genel bakış amacıyla yerel bir değer olarak kabul edileceğini unutmayın. Sınıfınız şablonları destekliyorsa, bu amaçla bir şablon kullanmak daha uygun olabilir. Tekil desenden kaçınmanın ancak yine de kullanışlı bir varsayılan değer sağlamanın bir diğer yolu, bu sınıfın değerleri için uygun bir varsayılan sağlayan başvuru türünde statik bir özelliği kullanıma sunmaktır.
Koleksiyon türü bağımlılık özellikleri
Koleksiyon türü bağımlılık özelliklerinin dikkate alınması gereken bazı ek uygulama sorunları vardır.
Koleksiyon türü bağımlılık özellikleri Windows Çalışma Zamanı API'sinde nispeten nadirdir. Çoğu durumda, öğelerin DependencyObject alt sınıfı olduğu koleksiyonları kullanabilirsiniz, ancak koleksiyon özelliğinin kendisi geleneksel bir CLR veya C++ özelliği olarak uygulanır. Bunun nedeni, koleksiyonların bağımlılık özelliklerinin söz konusu olduğu bazı tipik senaryolara uygun olmamasıdır. Örneğin:
- Genellikle bir koleksiyona animasyon eklemezsiniz.
- Genellikle bir koleksiyondaki öğeleri stil veya şablonla önceden doldurmazsınız.
- Koleksiyonlara bağlama önemli bir senaryo olsa da, bir koleksiyonun bağlama kaynağı olması için bağımlılık özelliği olması gerekmez. Bağlama hedefleri için, koleksiyon öğelerini desteklemek veya görünüm modeli desenlerini kullanmak için ItemsControl veya DataTemplate alt sınıflarının kullanılması daha normaldir. Koleksiyonlara ve koleksiyonlardan bağlama hakkında daha fazla bilgi için bkz. Ayrıntılı veri bağlama.
- Koleksiyon değişikliklerine yönelik bildirimler , INotifyPropertyChanged veya INotifyCollectionChanged gibi arabirimler aracılığıyla veya ObservableCollection<T'den> koleksiyon türü türetilerek daha iyi ele alınır.
Bununla birlikte, koleksiyon türü bağımlılık özelliklerine yönelik senaryolar vardır. Sonraki üç bölümde koleksiyon türü bağımlılık özelliğini uygulama hakkında bazı yönergeler sağlanır.
Koleksiyonu başlatma
Bağımlılık özelliği oluşturduğunuzda, bağımlılık özelliği meta verileri yoluyla varsayılan bir değer oluşturabilirsiniz. Ancak varsayılan değer olarak tek bir statik koleksiyon kullanmamaya dikkat edin. Bunun yerine, koleksiyon değerini, koleksiyon özelliğinin sahip sınıfı için sınıf oluşturucu mantığının bir parçası olarak benzersiz (örnek) bir koleksiyon olarak ayarlamanız gerekir.
// WARNING - DO NOT DO THIS
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
nameof(Items),
typeof(IList<object>),
typeof(ImageWithLabelControl),
new PropertyMetadata(new List<object>())
);
// DO THIS Instead
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
nameof(Items),
typeof(IList<object>),
typeof(ImageWithLabelControl),
new PropertyMetadata(null)
);
public ImageWithLabelControl()
{
// Need to initialize in constructor instead
Items = new List<object>();
}
DependencyProperty ve PropertyMetadata'nın varsayılan değeri DependencyProperty'nin statik tanımının bir parçasıdır. Varsayılan bir koleksiyon (veya başka bir örneklenmiş) değerin varsayılan değer olarak sağlanmasıyla, her sınıfın kendi koleksiyonuna sahip olması yerine, bu değer sınıfınızın tüm örnekleri arasında paylaşılır.
Bildirimleri değiştirme
Koleksiyonu bağımlılık özelliği olarak tanımlamak, "PropertyChanged" geri çağırma yöntemini çağıran özellik sisteminin özelliği sayesinde koleksiyondaki öğeler için otomatik olarak değişiklik bildirimi sağlamaz. Koleksiyonlar veya koleksiyon öğelerine (örneğin, veri bağlama senaryosu) yönelik bildirimler istiyorsanız , INotifyPropertyChanged veya INotifyCollectionChanged arabirimini uygulayın. Daha fazla bilgi için bkz. Ayrıntılı Veri Bağlama.
Bağımlılık özelliği güvenliğiyle ilgili dikkate alınması gereken hususlar
Bağımlılık özelliklerini genel özellikler olarak bildirin. Bağımlılık özelliği tanımlayıcılarını genel statik salt okunur üyeler olarak bildirin. Bir dil (korumalı gibi) tarafından izin verilen diğer erişim düzeylerini bildirmeye çalışsanız bile, bir bağımlılık özelliğine her zaman tanımlayıcı aracılığıyla özellik sistemi API'leriyle birlikte erişilebilir. Bağımlılık özellik tanımlayıcısının iç veya özel olarak bildirilmesi çalışmaz, çünkü özellik sistemi düzgün çalışamaz.
Sarmalayıcı özellikleri yalnızca kolaylık sağlamak için kullanılır. Sarmalayıcılara uygulanan güvenlik mekanizmaları bunun yerine GetValue veya SetValue çağrılarak atlanabilir. Bu nedenle sarmalayıcı özelliklerini genel tutun; aksi takdirde, yasal arayanların gerçek bir güvenlik avantajı sağlamadan mülkünüzü kullanmasını zorlaştırırsınız.
Windows Çalışma Zamanı, özel bağımlılık özelliğini salt okunur olarak kaydetmek için bir yol sağlamaz.
Bağımlılık özellikleri ve sınıf oluşturucuları
Sınıf oluşturucularının sanal yöntemleri çağırmaması gereken genel bir ilke vardır. Bunun nedeni, türetilmiş bir sınıfın temel başlatmasını gerçekleştirmek için oluşturucuların çağrılabilmesi ve oluşturulmakta olan nesne örneği henüz tamamen başlatılmadığında oluşturucu aracılığıyla sanal yönteme girilmesinin mümkün olmasıdır. DependencyObject'ten zaten türetilen herhangi bir sınıftan türetdiğinizde, özellik sisteminin kendi hizmetlerinin bir parçası olarak sanal yöntemleri çağırdığını ve kullanıma sunduğunu unutmayın. Çalışma zamanı başlatmayla ilgili olası sorunları önlemek için sınıfların oluşturucuları içinde bağımlılık özelliği değerlerini ayarlamayın.
C++/CX uygulamaları için bağımlılık özelliklerini kaydetme
C++/CX'te bir özelliği kaydetme uygulaması, hem üst bilgi ve uygulama dosyasına ayrılması hem de uygulama dosyasının kök kapsamında başlatmanın kötü bir uygulama olması nedeniyle C# dilinden daha karmaşıktır. (Visual C++ bileşen uzantıları (C++/CX), kök kapsamdaki statik başlatıcı kodunu doğrudan DllMain'e yerleştirirken, C# derleyicileri statik başlatıcıları sınıflara atar ve bu nedenle DllMain yük kilidi sorunlarından kaçının.) Burada en iyi yöntem, sınıf başına bir işlev olmak üzere bir sınıf için tüm bağımlılık özelliği kaydınızı yerine getiren bir yardımcı işlev bildirmektir. Ardından uygulamanızın kullandığı her özel sınıf için, kullanmak istediğiniz her özel sınıf tarafından kullanıma sunulan yardımcı kayıt işlevine başvurmanız gerekir. Her yardımcı kayıt işlevini uygulama oluşturucusunun (App::App() ) bir parçası olarak, öncesinde InitializeComponentbir kez çağırın. Bu oluşturucu yalnızca uygulamaya gerçekten ilk kez başvurulduğunda çalışır; örneğin, askıya alınmış bir uygulama yeniden başlatılırsa tekrar çalışmaz. Ayrıca, önceki C++ kayıt örneğinde görüldüğü gibi, her Register çağrısının etrafındaki nullptr denetimi önemlidir: bu, işlevi çağıranın özelliği iki kez kaydetmesini engelleyen bir güvencedir. Muhtemelen böyle bir kontrol olmadan yapılan ikinci bir kayıt çağrısı, özellik adının yinelenmiş olması nedeniyle uygulamanızı çökertebilir. C++/CX örneğinin koduna bakarsanız XAML kullanıcı ve özel denetim örneğinde bu uygulama desenini görebilirsiniz.
İlgili konular
Windows developer