Steve
Steve

Reputation: 29

Binding to Listbox programmatically in silverlight

I want a listbox that will show all the images and text "layers" that I have on my Canvas in silverlight. The code I have currently crashes when I try to view the listbox or when I'm viewing the listbox when I add an element. I can't figure out why. Can someone point me in the right direction with this?

XML -

                            <Grid DataContext="{Binding Path=Project}">
                                ...
                                ...
                                <TextBlock Name="textBlock1" Text="Layers" Margin="18,16,0,0" />

                                <StackPanel Grid.Row="1" Grid.RowSpan="2" Grid.ColumnSpan="2">
                                    <ListBox ItemsSource="{Binding Path=Elements}" Height="175" Name="listBox1" Width="172"/>
                                </StackPanel>

                            </Grid>

Project.cs

        //List of elements
    private ObservableCollection<FrameworkElement> elements;
    public ObservableCollection<FrameworkElement> Elements
    {
        get { return elements; }
        set
        {
            elements = value;
            NotifyPropertyChanged("Elements");
        }
    }
// An example of how an element is added to the Elements collection
// There are also image elements added similarly
private void AddTextElement(object param)
    {
        TextBlock textBlock = new TextBlock();
        textBlock.Text = "New Text";
        textBlock.Foreground = new SolidColorBrush(Colors.Gray);
        textBlock.FontSize = 25;
        textBlock.FontFamily = new FontFamily("Arial");
        textBlock.Cursor = Cursors.Hand;
        textBlock.Tag = null;


        this.Elements.Add(textBlock);
        numberOfElements++;


        this.SelectedElement = textBlock;
        this.selectedTextElement = textBlock;
    }

private void AddImageElement(object param)
    {
        bool? gotImage;
        string fileName;
        BitmapImage imageSource = GetImageFromLocalMachine(out gotImage, out fileName);


        if (gotImage == true)
        {
            Image image = new Image();
            OrderElements(image);
            image.Name = fileName;
            image.Source = imageSource;
            image.Height = imageSource.PixelHeight;
            image.Width = imageSource.PixelWidth;
            image.MaxHeight = imageSource.PixelHeight;
            image.MaxWidth = imageSource.PixelWidth;
            image.Cursor = Cursors.Hand;
            image.Tag = null;


            AddDraggingBehavior(image);
            image.MouseLeftButtonUp += element_MouseLeftButtonUp;

            this.Elements.Add(image);
            numberOfElements++;

            this.SelectedElement = image;
            this.SelectedImageElement = image;

        }
    }

Upvotes: 0

Views: 314

Answers (3)

Duncan Matheson
Duncan Matheson

Reputation: 1726

I'd guess it's crashing because you've got FrameworkElements that you've added to a Canvas, but then you're also adding them to your List. FrameworkElements generally don't like being added to the visual tree multiple times.

If this is the problem, something like this might work around it (bind your list to ElementsAsStrings):

    private ObservableCollection<FrameworkElement> elements;
    public ObservableCollection<FrameworkElement> Elements
    {
        get { return elements; }
        set
        {
            if(elements != null)
                elements.CollectionChanged -= onElementsChanged;
            elements = value;
            if(elements != null)
                elements.CollectionChanged += onElementsChanged;

            NotifyPropertyChanged("Elements");
            NotifyPropertyChanged("ElementsAsStrings");
        }
    }

    public IEnumerable<string> ElementsAsStrings
    {
        get
        {
            foreach(var element in Elements)
            {
                if(element is TextBox)
                    yield return (element as TextBox).Text;
                // More cases here
            }
        }
    }

    private void onElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("ElementsAsStrings");
    }

Upvotes: 0

Inga
Inga

Reputation: 482

Working with Images incorrectly will typically cause the crash; Show the code for implementation of your Elements and how you setting the images.

Also your XAML is missing ItemTemplate,where u would set the image and text.

Upvotes: 0

Johnny
Johnny

Reputation: 795

One reason might be, because you bind using Path property in your Grid element.

You should use binding source, and set your Project object as a staticresource which you can point to when you call binding source.

Like this:

<Window
    xlmns:local="NamespaceOfMyProject">

    <Window.Resources>
        <local:Project x:key="MyProjectResource" />
    </Window.Resources>

    <Grid DataContext="{Binding Source={StaticResource MyProjectResource}}>
    ....
    </Grid>
    ....
</Window>

Reason is: You use "Source" when you point to objects, and "Path" when you point to properties.

Another way to set the DataContext is to do it in the codebehind, using this C# code. But first give your grid a name, so it can be referenced in the codebehind:

<Grid x:Name="myGrid">

Codebehind:

myGrid.DataContext = new Project();

Upvotes: 1

Related Questions