#wpf #xaml #dynamic #tabitem #multibinding
#wpf #xaml #динамический #tabitem #многозадачность
Вопрос:
В моем приложении WPF я хочу динамически создавать TabItems в многоразовом UserControl, содержащем TabControl.
ItemsSource элемента TabControl привязан к экземпляру ObservableCollection через стандартную привязку к данным.
Я создаю элементы табуляции, подобные этому, ПОСЛЕ InitializeComponent()
того, как был вызван!
// ...
int itemCount = 0;
TabItem it = null;
it = new TabItem();
it.Header = "Sicherungen Relais";
tabItemList.Insert(itemCount , it);
it = new TabItem();
it.Header = "Lage der Bauteile";
tabItemList.Insert(itemCount , it);
it = new TabItem();
it.Header = "Schaltpläne";
tabItemList.Insert(itemCount , it);
it = new TabItem();
it.Header = "Tipps Tricks";
tabItemList.Insert(itemCount , it);
Хорошей новостью является то, что элементы действительно добавляются в TabControl с их соответствующими заголовками.
Теперь проблема возникает, когда WPF пытается применить к ним стиль ПОСЛЕ того, как окно стало видимым!
У меня есть этот стиль по умолчанию для TabItems:
<Style TargetType="{x:Type TabItem}"
BasedOn="{StaticResource TISTabItem}">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource convCategoryTabWidthConverter}">
<Binding RelativeSource="{RelativeSource AncestorType={x:Type TabControl}, Mode=FindAncestor}" />
<Binding RelativeSource="{RelativeSource AncestorType={x:Type TabControl}, Mode=FindAncestor}"
Path="ActualWidth" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
И преобразователь:
public class CategoryTabWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Count() < 1)
throw new ArgumentException("Values array passed is invalid.", "values");
if(values[0] == DependencyProperty.UnsetValue)
{
return 0; // Added for breakpoint. Bailing out here!!!
}
TabControl tabCtrl = values[0] as TabControl;
Double w = (tabCtrl.ActualWidth / tabCtrl.Items.Count);
w = (w <= 1) ? 0.0 : (w - 1);
return w;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Замечания: я использую этот конвертер и стиль в двух других местах, где TabItems статически добавляются в XAML! В этих случаях все работает нормально!
Однако, когда TabItems добавляются динамически, оба, TabControl RelativeSource и его ActualWidth оцениваются DependencyProperty.UnsetValue
как .
Я ожидаю некоторых логических ошибок, с которыми я столкнулся здесь.
Когда применяются стили? До того, как TabItems будут правильно добавлены во внутренние деревья или после? У кого-нибудь есть идеи о том, что я здесь делаю не так?
Я продолжу расследование и заранее благодарю всех вас за вашу помощь.
Ответ №1:
Решил это сам. Проблема заключалась в том, что я забыл, что элементы ItemsSource будут перенесены в экземпляр TabItem.
TabItem внутри TabItem на самом деле не имеет смысла.
Прямая вставка их в TabControl.Элементы заставили его работать на удивление.