Mam problemy z zaimplementowaniem niestandardowego DependencyObject:
Potrzebuję konwertera, który ustawia lub usuwa flagę wyliczenia we właściwości powiązanej. Dlatego stworzyłem IValueConverter wyprowadzony z FrameworkElement z dwoma DependencyProperties: Flag (flaga ustawiana/nieustawiona przez konwerter) i Flags (wartość/właściwość do modyfikacji). Nadrzędny UserControl (Name = EnumerationEditor) udostępnia właściwość, z którą powiązany jest konwerter.
ListBox generuje CheckBoxes i wystąpienia konwertera, które są używane do modyfikowania właściwości za pomocą DataTemplate. Każda instancja CheckBox/converter jest używana dla jednej flagi. Używam następującego kodu XAML:
<ListBox Name="Values" SelectionMode="Extended" BorderThickness="1" BorderBrush="Black" Padding="5">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type system:Enum}">
<DataTemplate.Resources>
<Label x:Key="myTestResource" x:Shared="False"
Content="{Binding}"
ToolTip="{Binding Path=Value, ElementName=EnumerationEditor}"
Foreground="{Binding Path=Background, ElementName=EnumerationEditor}"
Background="{Binding Path=Foreground, ElementName=EnumerationEditor}"/>
<converters:EnumerationConverter x:Key="EnumerationConverter" x:Shared="False"
Flag="{Binding}"
Flags="{Binding Path=Value, ElementName=EnumerationEditor}"/>
</DataTemplate.Resources>
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding}" IsChecked="{Binding Path=Value, ElementName=EnumerationEditor, Converter={StaticResource EnumerationConverter}}"/>
<ContentPresenter Content="{StaticResource myTestResource}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Dziwna rzecz: etykieta działa dobrze, ale konwerter nie. Pojawia się błąd:
System.Windows.Data Błąd: 4: Nie można znaleźć źródła powiązania z odwołaniem „ElementName=EnumerationEditor”. BindingExpression:Ścieżka=Wartość; PozycjaDanych=null; elementem docelowym jest „EnumerationConverter” (Name=''); właściwość docelowa to „Flagi” (typ „Enum”)
Nie rozumiem dlaczego, oprawa jest w zasadzie taka sama...
Oto kod konwertera:
public class EnumerationConverter : FrameworkElement, IValueConverter
{
#region IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Parity.Space;
}
#endregion
#region public Enum Flag { get; set; }
public Enum Flag
{
get { return (Enum)this.GetValue(EnumerationConverter.FlagProperty); }
set { this.SetValue(EnumerationConverter.FlagProperty, value); }
}
/// <summary>
/// Dependency property for Flag.
/// </summary>
public static readonly DependencyProperty FlagProperty = DependencyProperty.Register("Flag", typeof(Enum), typeof(EnumerationConverter));
#endregion
#region public Enum Flags { get; set; }
public Enum Flags
{
get { return (Enum)this.GetValue(EnumerationConverter.FlagsProperty); }
set { this.SetValue(EnumerationConverter.FlagsProperty, value); }
}
/// <summary>
/// Dependency property for Flags.
/// </summary>
public static readonly DependencyProperty FlagsProperty = DependencyProperty.Register("Flags", typeof(Enum), typeof(EnumerationConverter));
#endregion
}
2 odpowiedzi
Wniosek
Postanowiłem rozwiązać problem za pomocą dwóch UserControls; FlagControl i EnumerationEditorControl.
FlagControl ma dwie właściwości zależności
- Flaga (System.Enum): Określa, która flaga jest ustawiana/czyszczona przez kontrolkę
- Wartość(System.Enum): powiązana z właściwością/wartością, w której flaga jest ustawiona/wyczyszczona.
EnumerationEditorControl ma jedną właściwość zależności:
- Wartość(System.Enum): właściwość/wartość, w której ustawione są flagi.
EnumerationEditorControl używa DataTemplate do tworzenia wystąpienia FlagControls. DataTemplate wiąże właściwość FlagControl.Flag z DataContext, a właściwość FlagControl.Value z właściwością EnumerationEditorControl.Value.
W ten sposób nie potrzebuję konwertera, a logika jest wyraźnie oddzielona.
Dzięki za sugestie, komentarze i odpowiedzi!
Konwerter nie jest FrameworkElement
, więc nie powinien dziedziczyć z tej klasy, najlepiej użyć DependencyObject
.
Ponieważ konwerter nie znajduje się w żadnym drzewie, wiązanie nie będzie działać, możesz spróbować:
<converters:EnumerationConverter x:Key="EnumerationConverter" x:Shared="False"
Flag="{Binding}"
Flags="{Binding Path=Value, Source={x:Reference EnumerationEditor}}"/>
(Jednak należy to umieścić w Resources
UserControl
i odnieść się do niego, w przeciwnym razie x:Reference
spowoduje cykliczny błąd zależności).
Zauważ, że wiązanie Flag
próbuje związać się z DataContext
, co może nie działać, ponieważ DataContext
może nie być dziedziczone z tych samych powodów, co ElementName
i RelativeSource
nie będzie działać.
Podobne pytania
Powiązane pytania
Nowe pytania
c#
C # (wymawiane „patrz ostro”) jest językiem programowania wysokiego poziomu, statycznie typowanym, wieloparadygmatowym opracowanym przez firmę Microsoft. Kod C # zwykle jest przeznaczony dla rodziny narzędzi Microsoft .NET i czasów wykonywania, do których należą między innymi .NET Framework, .NET Core i Xamarin. Użyj tego tagu w przypadku pytań dotyczących kodu napisanego w C # lub C # formalnej specyfikacji.