none
Inline-Trigger RRS feed

  • Frage

  • Hallo!

    Ich möchte bei Änderung der TextBlock-InlinesCollection einen TabItem-Header farblich Kennzeichnen (Inlines vorhanden rot ansonsten grau).

    Dazu habe ich dem TabItem einen Style mit einem DataTrigger zugeordnet, der abhängig von der Tag-Eigenschaft des TabItem die Headerfarbe setzt:

    TabItem:

    <TabItem Header="Nicht vorhandene Datei(en)" Style="{StaticResource TabItemNVD}" Tag="{Binding ElementName=tblNVD, Path=Inlines, Converter={StaticResource tblInlinesZaehler}, UpdateSourceTrigger=PropertyChanged}" >
       

    Style:

    <Style TargetType="{x:Type TabItem}" x:Key="TabItemNVD">
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="Padding" Value="0" />
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border x:Name="grid" Background="LightGray">
                        <ContentPresenter>
                            <ContentPresenter.Content>
                                <TextBlock Margin="4,2" FontSize="12" Text="{TemplateBinding Content}" />
                            </ContentPresenter.Content>
                        </ContentPresenter>
                    </Border>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=Tag, RelativeSource={RelativeSource Self}}" Value="1">
                            <Setter TargetName="grid" Property="Background" Value="Red"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    Wie ersichtlich, wollte ich die Tag-Eigenschaft des TabItem über einen Value-Konverter, der die Inlines-Collection überwacht, ändern:

    Value-Konverter

    [System.Windows.Data.ValueConversion(typeof(System.Windows.Documents.InlineCollection), typeof(int))]
    public class TextBlockInline_Count_Converter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            // Hat der Value den richtigen Wert?
            if (value == null || value as System.Windows.Documents.InlineCollection == null) return 0;
    
            // Den Value in den gewünschten (und geprüften) Typ casten
            System.Windows.Documents.InlineCollection ilc = (System.Windows.Documents.InlineCollection)value;       //Wert als Inline-Collection
            return ilc.Count > 0 ? 1 : 0;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

    Die Inlines-Aufzählung des TextBlockes (tblNVD) aktualisiere ich in der CodeBehind.

    Mein Problem ist nun, dass eine Änderung der Inlines-Aufzählung (hinzufügen/löschen von Zeilen) den Value-Konverter (trotzUpdateSourceTrigger=PropertyChanged ) nicht auslöst.

    Woran kann das liegen?


    • Bearbeitet perlfred Dienstag, 20. März 2018 07:55
    Dienstag, 20. März 2018 07:53

Antworten

  • Hallo!

    Ich habe es jetzt so gelöst, dass ich zusätzlich eine Dependency Property führe (ilAnzahl), die synchron zu der Anzahl der Inline-Einträge geführt wird und verwende diese DP für das weitere Binding.

    DP: ilAnzahl

    private static readonly DependencyProperty InlineChangeProperty = DependencyProperty.Register("ilAnzahl", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
    private int ilAnzahl
    {
        get { return (int)GetValue(InlineChangeProperty); }
        set { SetValue(InlineChangeProperty, value); }
    }
    
     

    Aktualisieren des Inline.Count-Wertes als DP:

    private void tblNVD_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
        {
            if (tblNVD.Inlines.FirstInline != null) tblNVD.Inlines.Remove(tblNVD.Inlines.LastInline);       // Letzte Zeile löschen, wenn vorhanden
        }
        else
            tblNVD.Inlines.Add(new Run { Text = "Neue Zeile " + (tblNVD.Inlines.Count + 1).ToString() });  // Neue Zeile hinzufügen
        ilAnzahl = tblNVD.Inlines.Count;
    }
    

    Binden der DP an die Text-Eigenschaft des TextBlockes:

    <TextBlock Text="{Binding ilAnzahl}" DataContext="{Binding ElementName=wnd}" />
    

       

    • Als Antwort markiert perlfred Mittwoch, 21. März 2018 14:20
    Mittwoch, 21. März 2018 14:19

Alle Antworten

  • Hallo!

    Noch eine kleines (besser nachvollziehbares) Demo, was das Problem demonstriert:

    XAML:

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication2"
            mc:Ignorable="d"
            Title="Test Inlines-Änderung" Height="100" Width="300">
        <Grid>
            <Grid.Resources>
                <local:TextBlockInline_Count_Converter x:Key="tblInlinesZaehler" />
            </Grid.Resources>
            <TextBlock Name="tblNVD" Background="Aquamarine" VerticalAlignment="Top" HorizontalAlignment="Left" MinWidth="30" MouseLeftButtonDown="tblNVD_MouseLeftButtonDown"/>
            <TextBlock Name="tblAnzZeilen" HorizontalAlignment="Right" Text="{Binding ElementName=tblNVD, Path=Inlines, Converter={StaticResource tblInlinesZaehler}, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" />
        </Grid>
    </Window>

    CodeBehind:

    using System;
    using System.Windows;
    using System.Windows.Documents;
    using System.Windows.Input;
    
    
    namespace WpfApplication2
    {
        /// <summary>
        /// Interaktionslogik für MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void tblNVD_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
                {
                    if (tblNVD.Inlines.FirstInline != null) tblNVD.Inlines.Remove(tblNVD.Inlines.LastInline);       // Letzte Zeile löschen, wenn vorhanden
                }
                else tblNVD.Inlines.Add(new Run { Text = "Neue Zeile " + (tblNVD.Inlines.Count + 1).ToString() });  // Neue Zeile hinzufügen
            }
        }
    
        [System.Windows.Data.ValueConversion(typeof(System.Windows.Documents.InlineCollection), typeof(int))]
        public class TextBlockInline_Count_Converter : System.Windows.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                // Hat der Value den richtigen Wert?
                if (value == null || value as System.Windows.Documents.InlineCollection == null) return 0;
    
                // Den Value in den gewünschten (und geprüften) Typ casten
                System.Windows.Documents.InlineCollection ilc = (System.Windows.Documents.InlineCollection)value;       //Wert als Inline-Collection
                return ilc.Count > 0 ? 1 : 0;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return null;
            }
        }
    
    }

    Durch klicken auf den linken TextBlock wird jeweils eine Inline-Zeile hinzugefügt. Durch klicken bei gleichzeitig gedrückter STRG-Taste wird wiederum eine Inline-Zeile gelöscht.

    Der Text des rechten TextBlockes, der durch den Value-Converter die Anzahl der Inline-Zeilen anzeigen sollte, wird aber nicht aktualisiert :-(

        

    Wie kann ich aus der Collection eine DependencyProperty machen, bzw. bei der Collection-Änderung ein Property Changed Event auslösen???

    Dienstag, 20. März 2018 16:04
  • Hallo!

    Ich habe es jetzt so gelöst, dass ich zusätzlich eine Dependency Property führe (ilAnzahl), die synchron zu der Anzahl der Inline-Einträge geführt wird und verwende diese DP für das weitere Binding.

    DP: ilAnzahl

    private static readonly DependencyProperty InlineChangeProperty = DependencyProperty.Register("ilAnzahl", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
    private int ilAnzahl
    {
        get { return (int)GetValue(InlineChangeProperty); }
        set { SetValue(InlineChangeProperty, value); }
    }
    
     

    Aktualisieren des Inline.Count-Wertes als DP:

    private void tblNVD_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
        {
            if (tblNVD.Inlines.FirstInline != null) tblNVD.Inlines.Remove(tblNVD.Inlines.LastInline);       // Letzte Zeile löschen, wenn vorhanden
        }
        else
            tblNVD.Inlines.Add(new Run { Text = "Neue Zeile " + (tblNVD.Inlines.Count + 1).ToString() });  // Neue Zeile hinzufügen
        ilAnzahl = tblNVD.Inlines.Count;
    }
    

    Binden der DP an die Text-Eigenschaft des TextBlockes:

    <TextBlock Text="{Binding ilAnzahl}" DataContext="{Binding ElementName=wnd}" />
    

       

    • Als Antwort markiert perlfred Mittwoch, 21. März 2018 14:20
    Mittwoch, 21. März 2018 14:19