在silverlight中以编程方式绑定到Listbox

时间:2012-09-26 15:51:02

标签: c# wpf silverlight xaml binding

我想要一个列表框,它会在我的Canvas中以silverlight显示所有图像和文本“图层”。当我尝试查看列表框或当我在添加元素时查看列表框时,我当前崩溃的代码。我无法弄清楚为什么。有人能指出我正确的方向吗?

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;

        }
    }

3 个答案:

答案 0 :(得分:1)

可能有一个原因,因为您使用Grid元素中的Path属性进行绑定。

您应该使用绑定源,并将Project对象设置为静态资源,您可以在调用绑定源时指向该资源。

像这样:

<Window
    xlmns:local="NamespaceOfMyProject">

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

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

原因是:指向对象时使用“Source”,指向属性时使用“Path”。

设置DataContext的另一种方法是使用此C#代码在代码隐藏中执行此操作。但首先给你的网格命名,所以它可以在代码隐藏中引用:

<Grid x:Name="myGrid">

Codebehind:

myGrid.DataContext = new Project();

答案 1 :(得分:0)

错误地处理图像通常会导致崩溃;显示元素实现的代码以及设置图像的方式。

此外,您的XAML缺少ItemTemplate,您可以在其中设置图像和文本。

答案 2 :(得分:0)

我猜它会崩溃因为你已经添加了Canvas的FrameworkElements,但是你也将它们添加到你的List中。 FrameworkElements通常不喜欢多次添加到可视树中。

如果这是问题,这样的事情可能会解决(将列表绑定到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");
    }