Yukarıda belirtilen DataTrigger/Binding çözümünün kullanılması sorunu çözebilirsiniz. Birincisi, seçilen öğenin göreceli kaynağını bulamadığınız bir bağlanma uyarısıyla sonuçlanırsınız. Bununla birlikte, daha büyük sorun, veri şablonlarınızı karıştırmanız ve bunları bir ComboBox'a özel hale getirmenizdir.
WPF tasarımlarını daha iyi sunduğum çözüm, SelectedItemTemplate ve DropDownItemsTemplate özelliklerini ve her ikisi için de Seçici'yi kullanarak ayrı şablonlar belirleyebileceğiniz bir DataTemplateSelector kullanmasıdır.
public class ComboBoxTemplateSelector : DataTemplateSelector
{
public DataTemplate SelectedItemTemplate { get; set; }
public DataTemplateSelector SelectedItemTemplateSelector { get; set; }
public DataTemplate DropdownItemsTemplate { get; set; }
public DataTemplateSelector DropdownItemsTemplateSelector { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var parent = container;
// Search up the visual tree, stopping at either a ComboBox or
// a ComboBoxItem (or null). This will determine which template to use
while(parent != null && !(parent is ComboBoxItem) && !(parent is ComboBox))
parent = VisualTreeHelper.GetParent(parent);
// If you stopped at a ComboBoxItem, you're in the dropdown
var inDropDown = (parent is ComboBoxItem);
return inDropDown
? DropdownItemsTemplate ?? DropdownItemsTemplateSelector?.SelectTemplate(item, container)
: SelectedItemTemplate ?? SelectedItemTemplateSelector?.SelectTemplate(item, container);
}
}
Note: For simplicity, my example code here uses the new '?.' feature of C#6 (VS 2015). If you're using an older version, simply remove the '?' and explicitly check for null before calling 'SelectTemplate' above and return null otherwise like so:
return inDropDown
? DropdownItemsTemplate ??
((DropdownItemsTemplateSelector != null)
? DropdownItemsTemplateSelector.SelectTemplate(item, container)
: null)
: SelectedItemTemplate ??
((SelectedItemTemplateSelector != null)
? SelectedItemTemplateSelector.SelectTemplate(item, container)
: null)
Ben de basitçe oluşturur ve XAML kolaylık için yukarıdaki sınıfını döndüren bir biçimlendirme uzantısı dahil ettik.
public class ComboBoxTemplateSelectorExtension : MarkupExtension
{
public DataTemplate SelectedItemTemplate { get; set; }
public DataTemplateSelector SelectedItemTemplateSelector { get; set; }
public DataTemplate DropdownItemsTemplate { get; set; }
public DataTemplateSelector DropdownItemsTemplateSelector { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new ComboBoxTemplateSelector(){
SelectedItemTemplate = SelectedItemTemplate,
SelectedItemTemplateSelector = SelectedItemTemplateSelector,
DropdownItemsTemplate = DropdownItemsTemplate,
DropdownItemsTemplateSelector = DropdownItemsTemplateSelector
};
}
}
Ve işte bunları nasıl kullanıyorsunuz. Güzel, temiz ve berrak ve Şablonlarınız kalmak 'saf'
Note: 'is:' here is my xmlns mapping for where I put the class in code. Make sure to import your own namespace and change 'is:' as appropriate.
<ComboBox x:Name="MyComboBox"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{is:ComboBoxTemplateSelector
SelectedItemTemplate={StaticResource MySelectedItemTemplate},
DropdownItemsTemplate={StaticResource MyDropDownItemTemplate}}" />
İsterseniz de DataTemplateSelectors kullanabilirsiniz
...
<ComboBox x:Name="MyComboBox"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{is:ComboBoxTemplateSelector
SelectedItemTemplateSelector={StaticResource MySelectedItemTemplateSelector},
DropdownItemsTemplateSelector={StaticResource MyDropDownItemTemplateSelector}}" />
Veya karıştırıp maç! Burada seçili öğe için bir şablon kullanıyorum, ancak DropDown öğeleri için bir şablon seçici kullanıyorum. Bir Şablon veya seçilen veya açılır öğeler için bir TemplateSelector belirtmek yoksa beklediğiniz gibi
<ComboBox x:Name="MyComboBox"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{is:ComboBoxTemplateSelector
SelectedItemTemplate={StaticResource MySelectedItemTemplate},
DropdownItemsTemplateSelector={StaticResource MyDropDownItemTemplateSelector}}" />
Ayrıca, basitçe, tekrar veri türlerine bağlı olarak veri şablonları çözme düzenli düşer. Bu nedenle, örneğin, aşağıdaki durumda, seçilen öğenin şablonu açıkça ayarlanır, ancak açılır menüde, veri bağlamındaki nesnenin DataType'ı için hangi veri şablonu geçerli olur.
<ComboBox x:Name="MyComboBox"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{is:ComboBoxTemplateSelector
SelectedItemTemplate={StaticResource MyTemplate} />
Çözümünüz çalışıyor, ancak Çıktı penceresinde hatalar alıyorum. 'System.Windows.Veri Hatası: 4: Referans ile bağlama için kaynak bulunamadı 'RelativeSource FindAncestor, AncestorType =' System.Windows.Controls.ComboBoxItem ', AncestorLevel =' 1 ''. BindingExpression: Yol = IsSelected; Dataıtem = null; hedef öğe 'ContentPresenter' (Name = ''); target özelliği 'NoTarget' ('Object') ' – user2190035
'dır Bu hataları da gördüğümü hatırlıyorum. Ama artık projede (hatta şirkette) değilim, bu yüzden kontrol edemem özür dilerim. – Peter