简体   繁体   English

c#如何从Observable集合中获取列表框选择

[英]c# How to get Listbox selection from Observable Collection

I'm probably not even asking this correctly, I am new to c#, but trying to help my 14 year-old son learn. 我什至没有正确地问过这个问题,我是C#的新手,但是试图帮助我14岁的儿子学习。 I've created a listbox with items created with an ObservableCollection. 我已经创建了一个列表框,其中包含使用ObservableCollection创建的项目。 Here is the XAML: 这是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>

Here is how I created the ListBox Items: 这是我创建列表框项目的方式:

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 });
}

I thought I would just use the SelectionChanged="PrintText" property of the listbox so that when I clicked on a listbox item, it would just change a textblock's text value. 我以为我只使用列表框的SelectionChanged =“ PrintText”属性,这样当我单击列表框项时,它只会更改文本块的文本值。 Ultimately, that is all I am trying to do...set a textblock or textbox to be equal to the "id" value that is clicked on in the ListBox. 最终,这就是我要做的所有事情……将文本块或文本框设置为等于在列表框中单击的“ id”值。

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

Thanks very much for any insight! 非常感谢您的见解! I need it!! 我需要它!!

This is something that is much easier to do using data binding. 使用数据绑定更容易做到这一点。 You can bind the TextBlock.Text property directly to the ListBox using an ElementName binding: 您可以使用ElementName绑定将TextBlock.Text属性直接绑定到ListBox

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

Alternatively, if you set set SelectedValuePath="id" on the ListBox, then binding to SelectedValue will give you the "id" property: 另外,如果您在ListBox上设置set SelectedValuePath="id" ,则绑定到SelectedValue将为您提供“ id”属性:

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

As a side note (as @Rachel already noted in comments): you may as well just set the ItemsSource , rather than looping through and adding each manually. 附带说明一下(正如@Rachel在评论中已经指出的那样):您最好只设置ItemsSource ,而不是循环遍历并手动添加每个项目。 All you need is this: 您需要的是:

listBox1.ItemsSource = feed2;

Edit 编辑

Ok, if you wanted to use the procedural approach, here's how you would do it. 好的,如果您想使用过程方法,请按以下步骤进行。 (No one would recommend this approach, especially if you're learning/teaching. Try to make full use of data binding, and view-viewmodel separation.) (没有人会推荐这种方法,尤其是在您学习/教学时。请尝试充分利用数据绑定和视图-视图模型分离。)

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

If all you want to do is click an item in the ListBox and get it to show up in the TextBox, you don't need fancy binding (in that other answer) to do it. 如果您要做的只是单击ListBox中的一项并使其显示在TextBox中,则不需要花哨的装订(在其他答案中)。 You can simply add a MouseUp event in the ListBox XAML: 您只需在ListBox XAML中添加MouseUp事件:

MouseUp="ListBox1_MouseUp"

This would work similar to the SelectionChanged event you wanted to use. 这将类似于您要使用的SelectionChanged事件。

You then right-click that function name in the XAML page and select "Go to definition". 然后,在XAML页面中右键单击该函数名称,然后选择“转到定义”。 It will create the next function for you: 它将为您创建下一个功能:

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

Simply add in there to update the TextBox you want with the SelectedItem values from sender : 只需在其中添加以使用senderSelectedItem值更新所需的TextBox即可:

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;
    }
}

I later found that blockNameList and blockIdList are not accessible via intellisense because they are within the DataTemplate of the ListBox, so I put someBox and someOtherBox , as references to other TextBoxes you would have to add to the XAML, outside of the ListBox. 后来我发现,通过智能感知无法访问blockNameListblockIdList ,因为它们位于ListBox的DataTemplate中,因此我将someBoxsomeOtherBox引用为必须在someBox之外添加到XAML的其他someBox引用。 You would not re-write data inside the ListBox on the same item by clicking it. 通过单击它,您不会在同一项目的ListBox内重写数据。 Even if you could reach the template's TextBlock to do it, you'd just be re-writing that same item with its own values, since it would be the SelectedItem ! 即使您可以到达模板的TextBlock来执行此操作,您也将只使用其自己的值来重写同一项目,因为它将是SelectedItem

Even though there are those that don't recommend this approach because they like binding everything - and in some cases you want binding to occur so that controls on the page update as a result of dependencies (ie do one thing to cause another), I find that manual methods of clicking a button/item/control to update something are just fine and avoid all the model/MVVM BS that has taken over WPF and over-complicated it. 即使有些人因为喜欢绑定所有内容而不建议使用此方法,并且在某些情况下,您希望进行绑定,以便页面上的控件由于依赖关系而更新(即,做一件事情导致另一件事情),发现单击按钮/项目/控件来更新某些内容的手动方法很好,并且可以避免所有接管WPF并使其过于复杂的模型/ MVVM BS。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM