dotnet / dotnet/wpf

ContentControl doesn't update ControlTemplate when moved to another container (parent changes)

Open
#4,660 0 comments 2 reactions 0 assignees View on GitHub
.NET Framework
Dominant language
C#
Stars
7.7k
Forks
1.3k
Avg merge
1d 11h
Merged PRs (30d)
61

Description

* .NET Core Version: 5.0.301
* Windows version: 10 (20H2)
* Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes



**Problem description:**
ContentControl doesn't update ControlTemplate when moved to another container (parent changes). Is it a bug or the correct action?

**Minimal repro:**

I have two StackPanels. Each of them has defined a DataTemplate of the same LineItem type. When I move ContentControl from one to the other container I suspect that the view of the items will change. But it doesn't happen.

Create "WPF App (.NET 5)" or "WPF App (.NET Framework)" project and override MainWindow files:

```xaml





































```

```c#
namespace WpfApp7core
{
public class LineItem
{
public string Name { get; set; }
public string Value { get; set; }
}

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void Create1_Click(object sender, RoutedEventArgs e)
{
var li = new LineItem { Name = "Left", Value = Guid.NewGuid().ToString() };
column1.Children.Add(new ContentControl { Content = li });
}

private void Create2_Click(object sender, RoutedEventArgs e)
{
var li = new LineItem { Name = "Right", Value = Guid.NewGuid().ToString() };
column2.Children.Add(new ContentControl { Content = li });
}

private void MoveTo2_Click(object sender, RoutedEventArgs e)
{
foreach (FrameworkElement item in Enumerable.Range(0, column1.Children.Count).Select(i => column1.Children[i]).Cast().ToList())
{
RemoveFromParent(item); // Remove from column1
column2.Children.Add(item); // Add to column2
}
}

private void MoveTo1_Click(object sender, RoutedEventArgs e)
{
foreach (FrameworkElement item in Enumerable.Range(0, column2.Children.Count).Select(i => column2.Children[i]).Cast().ToList())
{
RemoveFromParent(item); // Remove from column2
column1.Children.Add(item); // Add to column1
}
}

public static void RemoveFromParent(FrameworkElement child)
{
switch (child.Parent)
{
case Panel panel: panel.Children.Remove(child); break;
case Decorator decorator: decorator.Child = null; break;
case ContentControl contentControl: contentControl.Content = null; break;
case ContentPresenter contentPresenter: contentPresenter.Content = null; break;
default: throw new Exception($"Unknown parent type {child.Parent.GetType()}");
}
}
}
}
```

MovingContentControlBug

**Expected behaviour:**
Each items on the left should be blue, and each on the right should be green.

**Unwanted solution:**
I found one solution. When I assign Content to null and then assign the previous value, ContentControl will update its view.

```c#
foreach (FrameworkElement item in Enumerable.Range(0, column1.Children.Count).Select(i => column1.Children[i]).Cast().ToList())
{
RemoveFromParent(item);
column2.Children.Add(item);

if (item is ContentControl cc)
{
var prev = cc.Content;
cc.Content = null;
cc.Content = prev;
}
}
```

But this solution becomes complicated when you have an extensive view tree.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.