Restyle WPF Control hosted in a WinForm app

297 Views Asked by At

I am trying to add Dark Theme support to my hobby app. App is WinForms, and I do not want to rewrite UI in WPF. So, instead I am trying to add couple of WPF controls into my app, mainly because they allow theming of a Scrollbar.

I am following this tutorial to host control: https://www.codeproject.com/Articles/739902/How-to-Easily-Host-WPF-Control-inside-Windows-Form

Everything works so far, except that I can't change Background color for my WPF control hosted in WinForms dynamically. I tried many things, raising property changed, calling SetValue etc, but the only way I could control Background/Foreground is by directly setting them in XAML, which is not what I want, because I want to be able to change color optionally.

Here's what I imagine is the closest to what I want:

System.Windows.Style style = new System.Windows.Style();
  style.TargetType = typeof(WpfControls.ListViewControl);
  style.Setters.Add(new System.Windows.Setter(WpfControls.ListViewControl.BackgroundProperty, System.Windows.Media.Brushes.Pink));
style.Setters.Add(new System.Windows.Setter(WpfControls.ListViewControl.ForegroundProperty, System.Windows.Media.Brushes.Red));
this.listViewControl.Style = style;

Color does not change. The code is here: https://github.com/TheIronWolfModding/WpfControlsWinFormsHost/blob/master/WindowsFormsHost_Test/Form1.cs

1

There are 1 best solutions below

0
On BEST ANSWER

Actually your code is working correctly. Your ListViewControl is misleading because it is a UserControl that contains a ListView control. You are correctly applying the style to the UserControl but the ListView is obscuring it so you can't see the changes. You can make the contained ListView's Background Transparent if you want proof.

To fix it you could change your XAML in the ListViewControl so that the ListView gets its foreground and background from the parent container.

<ListView x:Name="listView" ItemsSource="{Binding ListEntries}" ScrollViewer.VerticalScrollBarVisibility="Visible"
          Background="{Binding Parent.Background, RelativeSource={RelativeSource Self}}"
          Foreground="{Binding Parent.Foreground, RelativeSource={RelativeSource Self}}">
</ListView>

...or... since your intention may be to modify many other properties in the style too, and so you don't have to keep adding similar bindings for every one, you could instead get a reference to the contained ListView control and set its style directly. Instead, leave the XAML alone and add this to your Form1.cs code:

System.Windows.Style style = new System.Windows.Style();
  style.TargetType = typeof(System.Windows.Controls.ListView);
  style.Setters.Add(new System.Windows.Setter(WpfControls.ListViewControl.BackgroundProperty, System.Windows.Media.Brushes.Pink));
style.Setters.Add(new System.Windows.Setter(WpfControls.ListViewControl.ForegroundProperty, System.Windows.Media.Brushes.Red));

//this.listViewControl.Style = style;
var listview = listViewControl.FindName ("listView") as System.Windows.Controls.ListView;
if (listview != null) {
    listview.Style = style;
}

note: be sure you change the TargetType, it needs to match the ListView control for this to work.