0

I have a set of UserControls in a library, but because the library is in a different namespace than the MainWindow, I don't seem to be able to get one UserControl to retrieve List<features> from MainWindow.

I suspect this is because UserControl does not know of MainWindow, and it's not meant to, as it is in a DLL library. As the UserControl is in a DLL, it should be agnostic to namespaces, but still be able to get what it needs.

So below I put some XAML and relative C# code-behind where you can see on the UserControls ListBox, I'm trying to retrieve the features list from MainWindow.

<UserControl x:Class="FlatControls.MyListBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:FlatControls"
             mc:Ignorable="d" 
             d:DesignHeight="34" d:DesignWidth="100" MaxHeight="34" MaxWidth="100" x:Name="root">
   <ListBox x:Name="listBox">
</UserControl>
public MyListBox()
{
   InitializeComponent();
   listBox.Items = ???????????
}
<Window x:Class="MyApp.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:WpfApp4"
        xmlns:FC="clr-namespace:FlatControls;assembly=FlatControls"
        mc:Ignorable="d"
        Title="MainWindow" Height="1000" Width="1900" WindowState="Maximized" RenderOptions.BitmapScalingMode="Fant">
   <Grid>
      xyz
   </Grid>
<Window>
namespace MyApp
{
   public List<string> features = new List<string>();

   public MainWindow()
   {
      InitializeComponent();
      features.Add("Concave");
      features.Add("Convex");
   }
}

Any help would be greatly appreciated, whether it's via Binding, or code-behind :D

thatguy
  • 21,059
  • 6
  • 30
  • 40
Rafael Ventura
  • 284
  • 3
  • 13
  • I don't know what is the exact problem in your code but there is already a similar problem and a verified solution is available in stackoverflow. Please check the link: [Similar Solution Link](https://stackoverflow.com/questions/17422940/how-to-add-my-usercontrol-from-another-project-dll-into-my-wpf-solution) – Srijon Chakraborty Jan 16 '21 at 05:20
  • I had a look, unfortunately this informs the MainWindow that it can use the DLL, but the DLL is still not aware of MainWindow. I could add a similar reference to the UserControl to be able to point to the MainWindow, but that would make the UserControl not re-usable on other projects. – Rafael Ventura Jan 16 '21 at 13:40

2 Answers2

0

The ListBox in your custom UserControl has to bind its ItemsSource from somewhere. You should create an ItemsSource dependency property in your MyListBox to enable binding a collection from outside.

public partial class MyListBox : UserControl
{
   public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
      nameof(ItemsSource), typeof(IEnumerable), typeof(MyListBox), new PropertyMetadata());

   public IEnumerable ItemsSource
   {
      get => (IEnumerable)GetValue(ItemsSourceProperty);
      set => SetValue(ItemsSourceProperty, value);
   }

   public MyListBox()
   {
      InitializeComponent();
   }
}

In the markup for the MyListBox user control, bind to this property using a RelativeSource binding.

<UserControl x:Class="FlatControls.MyListBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:FlatControls"
             mc:Ignorable="d" 
             d:DesignHeight="34" d:DesignWidth="100" MaxHeight="34" MaxWidth="100" x:Name="root">
   <ListBox x:Name="listBox" ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType={x:Type local:MyListBox}}}"/>
</UserControl>

Now, in your MainWindow use the control (you already added the corresponding XML namespace).

<Window x:Class="MyApp.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:WpfApp4"
        xmlns:FC="clr-namespace:FlatControls;assembly=FlatControls"
        mc:Ignorable="d"
        Title="MainWindow" Height="1000" Width="1900" WindowState="Maximized" RenderOptions.BitmapScalingMode="Fant">
    <Grid>
       <FC:MyListBox x:Name="MyListBox"/>
    </Grid>
<Window>

Finally, assign the ItemsSource property of the MyListBox control with the features collection.

public MainWindow()
{
   InitializeComponent();

   features.Add("Concave");
   features.Add("Convex");

   MyListBox.ItemsSource = Features;
}

Alternatively, expose a property Features for your items and bind it in XAML.

public List<string> Features { get; }
<FC:MyListBox ItemsSource="{Binding Features}"/>
thatguy
  • 21,059
  • 6
  • 30
  • 40
0

As @thatguy said, you can use his way to do. Of course, if you like to write code in view.cs, you can use "FieldModifier" word to decorade you listbox in your MyListBox:

    <ListBox x:Name="listBox" x:FieldModifier="public" />

And in your MainWindow, you can get the listbox instance, of cource, you can set its itemsource like this:

 public MainWindow()
    {
        InitializeComponent();

        this.userControl.listBox.ItemsSource = new List<string>() { "11","22","33"};
    }
Kun Ma
  • 299
  • 1
  • 6