views:

185

answers:

2

Hi, I am trying to bind a dictionary's key to a row of the grid in a listbox, and bind the dictionary's value to another row of the grid. key's type is Book, a class thati wrote and the value's type is int. i want to write the elements of the class and the integer value in grid. Can you help me on this? I'm quite confused on determining the itemsSource and the data type to bind. thanks for helping

Edit: i forgot to say that i am using c# - wpf. =)


I sent the dictionary as the itemsSource, and i specified the dictionary as type in objectdataprovider tag, and tried to send the value (int) by this code:

< TextBlock Text="{Binding Value, Mode=OneWay}" Grid.Row="1" Width="65" >

and the selecteditem was shown as [myNameSpace.Book, 4] instead of only 4.


 BookListBox.ItemsSource = LibManager.Books;

this is what i wrote in Window.xaml.cs and Books is a BookList, where BookList is a type of dictionary< Book, int> .

and the xaml file:

< ListBox Height="571" HorizontalAlignment="Left" Margin="444,88,0,0" Name="BookListBox" VerticalAlignment="Top" Width="383" >

        < ListBox.Resources>
            <ObjectDataProvider x:Key="BookData" ObjectType="{x:Type local:BookList}"/>
        </ListBox.Resources>
        < ListBox.ItemTemplate>
            < DataTemplate>
                < Border  BorderThickness="2" BorderBrush="Black" Margin="5" CornerRadius="5" Width="350" >
                    < Grid DataContext="{StaticResource BookData}" >
                        < Grid.ColumnDefinitions>
                            < ColumnDefinition></ColumnDefinition>

                        </Grid.ColumnDefinitions>
                        < Grid.RowDefinitions>
                            < RowDefinition></RowDefinition>
                            < RowDefinition></RowDefinition>


                        < /Grid.RowDefinitions>

                        < Label Content="count: " />
                        < TextBlock Text="{Binding Value, Mode=OneWay}" Grid.Row="1" Width="65"></TextBlock>


                    < /Grid>
                < /Border>

            < /DataTemplate>
        < /ListBox.ItemTemplate>
    < /ListBox>

there is one more problem with my code-- i cant see the listed items in listbox. i mean i could get the values by ListBox.SelectedItem but couldnt see in the listbox. thus i cant be sure if i could pass the integer value to where i want. So i think i also need help for this problem first... i write a label that i write by hand, and another label that should be filled by data binding in the same row but i can just see the first label, but i can reach the value in code behind.

A: 

Remove DataContext="{StaticResource BookData}" from the Grid element.

The ObjectDataProvider will create a new, empty BookList, and your TextBlock is inheriting that DataContext. If you remove that attribute, the TextBlock will get its DataContext from the current item in the ItemsControl, which will be the KeyValuePair for that row. You can probably remove the ObjectDataProvider element completely since you are creating the data in code.

Quartermeister
but shouldnt i implement the object type?
cemregoksu
@cemregoksu: I'm not sure what you mean by 'implement the object type'. You don't need to provide WPF with any type information; it will read it from the runtime type of the object. ObjectDataProvider is used if you want to create an object in XAML using a method call or supplying constructor parameters. Since you already have an object, you can just assign it to ItemsSource.
Quartermeister
+1  A: 

Below code will show the following:

1
Book 1
-------
2
Book 2
-------
3
Book 3

SelectedBookIndex will be set to the index of the selected book, at start the second book will be selected.

XAML:

<Window x:Class="TestDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">

    <StackPanel>
        <ListBox 
            ItemsSource="{Binding Path=Books}"
            SelectedValuePath="Value"
            SelectedValue="{Binding Path=SelectedBookIndex}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="Black" BorderThickness="2">
                        <StackPanel>
                            <TextBlock Text="{Binding Path=Value}" />
                            <TextBlock Text="{Binding Path=Key.Name}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</Window>

Code behind:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;

namespace TestDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Books = new Dictionary<Book, int>();
            Books.Add(new Book() { Name = "Book 1"}, 1);
            Books.Add(new Book() { Name = "Book 2" }, 2);
            Books.Add(new Book() { Name = "Book 3" }, 3);

            SelectedBookIndex = 2;

            DataContext = this;
        }

        public Dictionary<Book, int> Books { get; set; }

        private int _selectedBookIndex;
        public int SelectedBookIndex
        {
            get { return _selectedBookIndex; }
            set
            {
                _selectedBookIndex = value;
                Debug.WriteLine("Selected Book Index=" + _selectedBookIndex);
            }
        }
    }

    public class Book
    {
        public string Name { get; set; }
    }
}
Wallstreet Programmer
that solution worked perfectly.thank you very much=)
cemregoksu