Search code examples
wpfcustom-controlsitemscontrol

WPF customized ItemsControl and Binding


I have created a custom ItemsControl called Toolbox. I want to be able to display images in that Toolbox - it is a part of a diagram designer.

My xaml looks like this:

<d:Toolbox ItemsSource="{Binding}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>

                                    <Image Source="{Binding Library}"/>

                                </DataTemplate>

                            </ItemsControl.ItemTemplate>
                        </d:Toolbox>

and my ViewModel:

 public ObservableCollection<ElectricalLibrary> l = null;
        public ObservableCollection<Image> _images = null;
        public ObservableCollection<Image> Library

        {
            get
            {
                if (l == null)
                {
                    DataAccessLayerClass dc = new DataAccessLayerClass();
                    dc.LoadComponents();
                    l = dc.Library;
                    foreach (ElectricalLibrary lib in l) { 
                        Image finalImage = new Image();
                        finalImage.Width = 80;
                        BitmapImage logo = new BitmapImage();
                        logo.BeginInit();
                        logo.UriSource = new Uri(lib.url.ToString());
                        logo.EndInit();

                        finalImage.Source = logo;
                        MessageBoxResult result = MessageBox.Show(logo.UriSource.ToString());  

                        _images.Add(finalImage);
                    }



                }
                return _images;
            }
            set { _images = value; }
        }

Ands this is a resource file for Toolbox itself:

<Style TargetType="{x:Type s:Toolbox}">
        <Setter Property="SnapsToDevicePixels"
                Value="true" />
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                            Padding="{TemplateBinding Control.Padding}"
                            BorderBrush="{TemplateBinding Border.BorderBrush}"
                            Background="{TemplateBinding Panel.Background}"
                            SnapsToDevicePixels="True">
                        <ScrollViewer VerticalScrollBarVisibility="Auto">
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <WrapPanel Margin="0,5,0,5"
                               ItemHeight="{Binding Path=DefaultItemSize.Height, RelativeSource={RelativeSource AncestorType=s:Toolbox}}"
                               ItemWidth="{Binding Path=DefaultItemSize.Width, RelativeSource={RelativeSource AncestorType=s:Toolbox}}" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>

I store only the URLs of the images in the database, the images are stored on a disc. I take the entity object and create an image, add it into an ObservableCollection of images and bind Image control to LIbrary in xaml.

Obviously, the code does not work. But how to make it work? The list with images is loaded correctly.

Thanks for help.


Solution

  • ****EDIT**** Right - I have managed to get the code to work after some changes. Change your Library property to return a list of Uri's set from your database Objects - make sure you actually return something. I suggest the following for your property (change it if you need a more robust property which doesnt refetch every time there is get...

    public ObservableCollection<Uri> Library
    {
        get
        {
            OberservableCollection<Uri> library = new OberservableCollection<Uri>();
            DataAccessLayerClass dc = new DataAccessLayerClass();
            dc.LoadComponents();
    
            foreach (ElectricalLibrary lib in dc.Library)
            {
                library.Add(new Uri(lib.url.ToString()));
            }
    
            return library;
        }
    

    Then your XAML can look like this:

                          <d:Toolbox ItemsSource="{Binding Library}">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
    
                                        <Image Source="{Binding}"/>
    
                                    </DataTemplate>
    
                                </ItemsControl.ItemTemplate>
                            </d:Toolbox>
    

    Doing this makes it work fine for me.

    Original text left for historical reasons

    You seem to be binding the image to the entire collection. If it is just a single list of images you need then the ItemsSource of you toolbox should be the Library collection with an image as part of the DataTemplate (I cant test this right now so it may not be 100% accurate code)

    <d:Toolbox ItemsSource="{Binding Library}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                    <Image Source="{Binding}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </d:Toolbox>