two usercontrols with different dependency properties have the same content

Jungbluth 20 Reputation points
2025-02-26T09:06:20.7066667+00:00

i have a usercontrol called filtercontrol that's in a in a itemscontrol. the itemscontrol ist bound to a observablecollection. the usercontrol has a dependency property that's set a guid. wenn the guid is set the usercontrol gets data from a source to fill itself.

when i run the program the usercontrols have different guid's that's returns different data but both of them display the data of the last.

xaml itemscontrol

<ItemsControl
                            Name="FiltersPanel"
                            Grid.Row="1"
                            Grid.Column="0"
                            Grid.ColumnSpan="2"
                            Margin="5,5,5,5">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Vertical" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Border BorderBrush="#ABADB3" BorderThickness="1">
                                        <Grid Margin="5" Tag="{Binding Path=Guid}">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition />
                                                <RowDefinition MaxHeight="300" />
                                            </Grid.RowDefinitions>
                                            <local:FilterControl Guid="{Binding Path=Guid}" />
                                            <StackPanel
                                                Grid.Row="1"
                                                Grid.Column="0"
                                                Orientation="Horizontal">
                                                <Button
                                                    Name="BtnEditFilter"
                                                    Margin="5"
                                                    Click="BtnEditFilter_Click"
                                                    Content="Bearbeiten"
                                                    Tag="{Binding Path=Guid}" />
                                                <Button
                                                    Name="BtnDeleteFilter"
                                                    Margin="5"
                                                    Click="BtnDeleteFilter_Click"
                                                    Content="Löschen"
                                                    Tag="{Binding Path=Guid}" />
                                            </StackPanel>
                                        </Grid>
                                    </Border>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Grid>

xaml filtercontrol

<UserControl
    x:Class="MailFilter.WPF.FilterControl"
    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:local="clr-namespace:MailFilter.WPF"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    MinWidth="300"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <TextBlock
            Grid.Row="0"
            Grid.Column="0"
            Margin="5"
            FontWeight="Bold"
            Text="Bedingungen" />
        <ItemsControl
            Name="RulesPanel"
            Grid.Row="1"
            Grid.Column="0"
            Margin="5">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid
                        Margin="5"
                        Loaded="Grid_Loaded"
                        Tag="{Binding Path=Guid}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="10" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <TextBlock
                            Grid.Row="0"
                            Grid.RowSpan="2"
                            Grid.Column="0"
                            Margin="-3,-10,0,0"
                            FontWeight="Bold"
                            Loaded="TextBlock_Loaded"
                            Text="{Binding Path=DisplayChainText}" />
                        <TextBlock
                            Grid.Row="0"
                            Grid.Column="1"
                            MaxHeight="45"
                            Margin="5"
                            Text="{Binding Path=DisplayText}"
                            TextTrimming="CharacterEllipsis" />
                        <StackPanel
                            Grid.Row="1"
                            Grid.Column="1"
                            Orientation="Horizontal">
                            <Button
                                Name="BtnDeleteRule"
                                Margin="5"
                                Click="BtnDeleteRule_Click"
                                Content="Löschen"
                                Tag="{Binding Path=Guid}" />
                            <Button
                                Name="BtnRuleDataContextPopOut"
                                Margin="5"
                                Click="BtnRuleDataContextPopOut_Click"
                                Tag="{Binding Path=Guid}"
                                Visibility="Collapsed">
                                <Image Source="/popout-icon_black_20x20.png" />
                            </Button>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <TextBlock
            Grid.Row="2"
            Grid.Column="0"
            Margin="5"
            FontWeight="Bold"
            Text="Aktionen" />
        <ItemsControl
            Name="ActionsPanel"
            Grid.Row="3"
            Grid.Column="0"
            Margin="5">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <TextBlock
                            Grid.Row="0"
                            Grid.Column="0"
                            Margin="5"
                            Text="{Binding Path=DisplayText}" />
                        <Button
                            Name="BtnDeleteAction"
                            Grid.Row="1"
                            Grid.Column="0"
                            Margin="5"
                            HorizontalAlignment="Left"
                            Click="BtnDeleteAction_Click"
                            Content="Löschen"
                            Tag="{Binding Path=Guid}" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</UserControl>

codebehind filtercontrol

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
 
namespace MailFilter.WPF
{
    /// <summary>
    /// Interaktionslogik für FilterControl.xaml
    /// </summary>
    public partial class FilterControl : UserControl
    {
        private static readonly ObservableCollection<RuleRepresenter> _rules = [];
        private static readonly ObservableCollection<ActionRepresenter> _actions = [];
        private static readonly Core.MailFilter mailFilter = MainWindow.Instance.MailFilter;
        public static readonly DependencyProperty guid = DependencyProperty
            .Register("Guid",
            typeof(string),
            typeof(FilterControl),
            new PropertyMetadata(default(string), new PropertyChangedCallback(UpdateControl)));
 
        public string Guid
        {
            get => (string)GetValue(guid);
            set => SetValue(guid, value);
        }
 
        public FilterControl()
        {
            InitializeComponent();
            RulesPanel.ItemsSource = _rules;
            ActionsPanel.ItemsSource = _actions;
        }
 
        private static void UpdateControl(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            IEnumerable<FilterRule> rules = from filter in mailFilter.Filters
                                            where filter.Guid == e.NewValue.ToString()
                                            from rule in filter.Rules
                                            select rule;
 
            IEnumerable<FilterAction> actions = from filter in mailFilter.Filters
                                                where filter.Guid == e.NewValue.ToString()
                                                from action in filter.Actions
                                                select action;
 
            _rules.Clear();
            _actions.Clear();
 
            foreach (FilterRule rule in rules)
            {
                _rules.Add(RepresenterConverter.ConvertToRepresenter(rule));
            }
 
            foreach (FilterAction action in actions)
            {
                _actions.Add(RepresenterConverter.ConvertToRepresenter(action));
            }
        }
 
        private void BtnDeleteRule_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Bedingung wirklich löschen?", "MailFilter", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                Button button = (sender as Button)!;
                RuleRepresenter ruleRepresenter = (from rule in _rules
                                                   where rule.Guid == button.Tag.ToString()
                                                   select rule).First();
 
                _rules.RemoveAt(_rules.IndexOf(ruleRepresenter));
                MainWindow.Instance.MailFilter.RemoveRule(ruleRepresenter.Guid);
            }
        }
 
        private void BtnDeleteAction_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Aktion wirklich löschen?", "MailFilter", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                Button button = (sender as Button)!;
                ActionRepresenter actionRepresenter = (from action in _actions
                                                       where action.Guid == button.Tag.ToString()
                                                       select action).First();
 
                _actions.RemoveAt(_actions.IndexOf(actionRepresenter));
                MainWindow.Instance.MailFilter.RemoveAction(actionRepresenter.Guid);
            }
        }
 
        private void BtnRuleDataContextPopOut_Click(object sender, RoutedEventArgs e) =>
            new RuleDataContextPopOutWindow(
            (from rule in _rules
             where rule.Guid == (sender as Button)!.Tag.ToString()
             select rule.DataContext).First())
            .Show();
 
        private void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            Grid grid = (sender as Grid)!;
 
            if ((from rule in _rules where rule.Guid == grid.Tag.ToString() select rule.RuleType).First() == 1)
            {
                (from object stackPanel in grid.Children
                 where stackPanel is StackPanel
                 from Button button in (stackPanel as StackPanel)!.Children
                 where button is Button && button.Name == "BtnRuleDataContextPopOut"
                 select button).First().Visibility = Visibility.Visible;
            }
        }
 
        private void TextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            TextBlock textBlock = (sender as TextBlock)!;
            if (textBlock.Text == "O\nR")
            {
                textBlock.Margin = new Thickness(-3, -3, 0, 0);
            }
        }
    }
}

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,833 questions
0 comments No comments
{count} votes

Accepted answer
  1. Hongrui Yu-MSFT 4,605 Reputation points Microsoft Vendor
    2025-02-27T07:44:53.8866667+00:00

    Hi, @Jungbluth. Welcome to Microsoft Q&A. 

    Reason

    The callback function UpdateControl that you registered for the dependency property Guid will run during the initial assignment. Assuming that your first ItemsControl (x:Name="FiltersPanel") has two values initially assigned, UpdateControl will run twice. Since UpdateControl contains _rules.Clear(); _actions.Clear(); and _rules and _actions are static properties, they will only display the last one and both display the same data.

    Solution

    1.Do not use static modified _rules and _actions to bind data, static will share the data to be bound. You could update data directly on RulesPanel and ActionsPanel. Reference code:

    public FilterControl()
    {
        InitializeComponent();
        //Do not use _rules and _actions for binding
        //RulesPanel.ItemsSource = _rules;
        //ActionsPanel.ItemsSource = _actions;
    }
    
    private static void UpdateControl(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //Get RulesPanel and ActionsPanel
        var grid = (d as FilterControl).Content as Grid;
        var rulesPanel = grid.Children.OfType<ItemsControl>().Where(p=> "RulesPanel".Equals(p.Name)).FirstOrDefault();
        var actionsPanel = grid.Children.OfType<ItemsControl>().Where(p => "ActionsPanel".Equals(p.Name)).FirstOrDefault();
    
        IEnumerable<FilterRule> rules = from filter in mailFilter.Filters
                                        where filter.Guid == e.NewValue.ToString()
                                        from rule in filter.Rules
                                        select rule;
    
        IEnumerable<FilterAction> actions = from filter in mailFilter.Filters
                                            where filter.Guid == e.NewValue.ToString()
                                            from action in filter.Actions
                                            select action;
    
        //Update data directly on RulesPanel and ActionsPanel
        rulesPanel.Items.Clear();
        actionsPanel.Items.Clear();
    
    
        foreach (FilterRule rule in rules)
        {
            rulesPanel.Items.Add(RepresenterConverter.ConvertToRepresenter(rule));
        }
    
        foreach (FilterAction action in actions)
        {
            actionsPanel.Items.Add(RepresenterConverter.ConvertToRepresenter(action));
        }
    
        rulesPanel.Items.Refresh();
        actionsPanel.Items.Refresh();
    }
    

    2Make sure that the data stored in mailFilter should be separated from the data bound to FiltersPanel.ItemsSource.

    3.At this time, the result of the Linq query may be empty, please change First to FirstOrDefault, for example:

    Picture1


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.