c#如何从Observable Collection中选择列表框

时间:2013-12-23 19:35:58

标签: c# wpf xaml listbox

我可能甚至没有正确地问这个问题,我是c#的新手,但是试图帮助我14岁的儿子学习。我创建了一个列表框,其中包含使用ObservableCollection创建的项目。这是XAML:

<ListBox x:Name="listBox1" ItemsSource="{Binding}" Margin="105,205,886,63"
   IsTabStop="True" SelectionChanged="PrintText" 
   ScrollViewer.VerticalScrollBarVisibility="Hidden" TabIndex="5" FontSize="36" 
   Background="Transparent" Foreground="#FF55B64C" FontFamily="Arabic Typesetting" 
   FontWeight="Bold" IsDoubleTapEnabled="False" SelectionMode="Single" >
     <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Name="blockNameList" Text="{Binding name}"/>
                <TextBlock Text=" #"/>
                <TextBlock Name="blockIdList" Text="{Binding id}"/>
            </StackPanel>
        </DataTemplate>
     </ListBox.ItemTemplate> 
</ListBox>

以下是我创建ListBox项目的方法:

var client = new HttpClient();
var uri = new Uri("http://theurlImusing");
Stream respStream2 = await client.GetStreamAsync(uri);
// DataContractJsonSerializer ser2 = new DataContractJsonSerializer(typeof(RootObject));
// RootObject feed2 = (RootObject)ser2.ReadObject(respStream2);
DataContractJsonSerializer ser = null;
ser = new DataContractJsonSerializer(typeof(ObservableCollection<RootObject>));
ObservableCollection<RootObject> feed2 = ser.ReadObject(respStream2) as ObservableCollection<RootObject>;

var cardList = new List<RootObject>();

foreach (RootObject returnfeed in feed2)
{
    string cid = returnfeed.id;
    string cardname = returnfeed.name;
    listBox1.Items.Add(new RootObject { id=cid, name=cardname });
}

我以为我只会使用列表框的SelectionChanged =“PrintText”属性,这样当我点击列表框项时,它只会更改文本块的文本值。最终,这就是我要做的所有事情......将文本块或文本框设置为等于ListBox中单击的“id”值。

void PrintText(object sender, SelectionChangedEventArgs args)
{
     //What do I put in here??    
}

非常感谢您的任何见解!我需要它!!

2 个答案:

答案 0 :(得分:2)

使用数据绑定更容易做到这一点。您可以使用TextBlock.Text绑定将ListBox属性直接绑定到ElementName

<TextBox Text="{Binding ElementName=listBox1,Path=SelectedItem.id}" />

或者,如果您在ListBox上设置了set SelectedValuePath="id",那么绑定到SelectedValue将为您提供“id”属性:

<ListBox x:Name="listBox1" SelectedValuePath="id" ... />
<TextBox Text="{Binding ElementName=listBox1,Path=SelectedValue}" />

作为附注(正如@Rachel在评论中已经注意到的那样):您也可以设置ItemsSource,而不是循环并手动添加每个。{1}}。所有你需要的是:

listBox1.ItemsSource = feed2;

修改

好的,如果你想使用程序方法,这就是你将如何做到的。 (没有人会推荐这种方法,特别是如果你正在学习/教学。尝试充分利用数据绑定和视图模型分离。)

void PrintText(object sender, SelectionChangedEventArgs args)
{
    var listBox = (ListBox)sender;
    RootObject selectedItem = listBox.SelectedItem;
    someTextBox.Text = selectedItem.id;
}

答案 1 :(得分:0)

如果要做的只是单击ListBox中的项目并让它显示在TextBox中,则不需要花式绑定(在其他答案中)来执行此操作。您只需在MouseUp XAML:

中添加ListBox事件即可
MouseUp="ListBox1_MouseUp"

这与您想要使用的SelectionChanged事件类似。

然后右键单击XAML页面中的该函数名称,并选择“转到定义”。它将为您创建下一个功能:

private void ListBox1_MouseUp(object sender, MouseButtonEventArgs e)
{
}

只需添加来自SelectedItem的{​​{1}}值来更新所需的TextBox:

sender

我后来发现private void ListBox1_MouseUp(object sender, MouseButtonEventArgs e) { ListBox lstBox = (ListBox)sender; ListBoxItem item = lstBox.SelectedItem; if (item != null) // avoids exception when an empty line is clicked { someBox.Text = item.name; someOtherBox.Text = item.id; } } blockNameList无法通过intellisense访问,因为它们位于ListBox的DataTemplate中,因此我将blockIdListsomeBox作为参考到其他TextBox,你必须添加到ListBox之外的XAML。您不会通过单击在同一项目上的ListBox内重写数据。即使您可以使用模板的TextBlock来执行此操作,您只需使用自己的值重写相同的项目,因为它将是someOtherBox

即使有些人不推荐这种方法,因为他们喜欢绑定所有内容 - 在某些情况下,你希望发生绑定,以便页面上的控件因依赖性而更新(即做一件事导致另一个),我发现单击按钮/项目/控件来更新内容的手动方法很好,并且避免所有已接管WPF且过度复杂的模型/ MVVM BS。