Silverlight如何在数据模板中使用按钮时提升列表框的选定项目

发布于 2024-11-29 09:49:04 字数 1889 浏览 8 评论 0原文

在列表框控件中,我有一个由文本和按钮组成的数据模板。鉴于 Silverlight/WPF 的性质,当我单击列表框项中的按钮时,在选择列表框项之前按钮事件将被捕获。因此,如果我尝试传递所选列表框项目的记录 ID,目前只能通过首先单击并选择列表框项目,然后单击按钮来实现。

有没有一种方法可以促进列表框项目的选择,以便在创建列表框项目时我能够单击列表框项目中的按钮并调用一些事件(selectionChanged?),这将允许我捕获所选内容记录 id 并将其用于其他一些操作(作为方法中的参数传递等)。我使用 Simple MVVM 工具包来实现此实现,所以我想知道是否可以在 viewModel 中处理此问题,或者是否需要在后面的控件代码中处理此问题,然后将选择推送到 viewModel。

列表框控件呈现为:

<ListBox x:Name="ResultListBox"
             HorizontalAlignment="Stretch"
             Background="{x:Null}"
             Grid.Row="1"
             BorderThickness="0" HorizontalContentAlignment="Stretch"
             ItemContainerStyle="{StaticResource ListBoxItemStyle1}"
             ItemsSource="{Binding SearchResults[0].Results}"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             Style="{StaticResource ListBoxStyle1}">

        <ListBox.ItemTemplate>

            <DataTemplate>
                <dts:TypeTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch">
                    <!--  Template 1  -->
                    <formatter:TypeTemplateSelector.CFSTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Product />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.CFSTemplate>

                    <!--  Template 2  -->
                    <formatter:TypeTemplateSelector.PersonTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Person  />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.PersonTemplate>

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

在数据模板(用户控件)中驻留按钮以及许多其他字段。除非有要求,否则我将暂时忽略该代码。

提前致谢!

Within a Listbox control I have a Data Template which consists of text and a button. Given the nature of Silverlight/WPF when I click on the button within the listbox item the button event is trapped before the listbox item is selected. Therefore if I am trying to pass the record ID of the selected listbox item I am currently only able to do so by first clicking and selecting the listbox item and then clicking on the button.

Is there a way to promote the selection of the listbox item so that when the listbox items are created I have the ability to click on the button within the listbox item and some event (selectionChanged ?) is invoked which would allow me to capture the selected record id and use it for some other action ( pass as a parameter in a method etc). I'm using Simple MVVM toolkit for this implementation so I was wondering if this could be handled in the viewModel or if I would need to handle this in the controls code behind and then push the selection to the viewModel.

The listbox control is presented as:

<ListBox x:Name="ResultListBox"
             HorizontalAlignment="Stretch"
             Background="{x:Null}"
             Grid.Row="1"
             BorderThickness="0" HorizontalContentAlignment="Stretch"
             ItemContainerStyle="{StaticResource ListBoxItemStyle1}"
             ItemsSource="{Binding SearchResults[0].Results}"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             Style="{StaticResource ListBoxStyle1}">

        <ListBox.ItemTemplate>

            <DataTemplate>
                <dts:TypeTemplateSelector Content="{Binding}" HorizontalContentAlignment="Stretch">
                    <!--  Template 1  -->
                    <formatter:TypeTemplateSelector.CFSTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Product />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.CFSTemplate>

                    <!--  Template 2  -->
                    <formatter:TypeTemplateSelector.PersonTemplate>
                        <DataTemplate>
                            <qr:ucIndex_Person  />
                        </DataTemplate>
                    </formatter:TypeTemplateSelector.PersonTemplate>

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

Within the datatemplate (user control) resides the button along with a number of other fields. I'll omit that code for the time being unless requested.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枉心 2024-12-06 09:49:04

将其放入您的 ListBox.Resources

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>

并将其放在后面的代码中

protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
    ListBoxItem item = (ListBoxItem)sender;
    item.IsSelected = true;
}

您也可以使用以下代码,该代码不使用代码隐藏,但是它只会使 ListBoxItem 保持选中状态,只要它有键盘焦点。一旦焦点离开,该项目将变为未选中

<Style TargetType="ListBoxItem">
  <Style.Triggers>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
      <Setter Property="IsSelected" Value="True" />
    </Trigger>
  </Style.Triggers>
</Style>

编辑

由于Silverlight没有EventSetters,您可以使用ListBox的Loaded事件并将以下内容添加到后面的代码中:

private void ResultListBox_Loaded(object sender, RoutedEventArgs e)
{
    ListBox list = (ListBox)sender;
    list.GotFocus += ResultListBox_GotFocus;
}

void ResultListBox_GotFocus(object sender, RoutedEventArgs e)
{
    var item = FindAncester<ListBoxItem>((DependencyObject)e.OriginalSource);
    if (item != null) item.IsSelected = true;
}

T FindAncester<T>(DependencyObject current) 
    where T : DependencyObject
{
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}

这将捕获ListBox的Focus事件,需要触发焦点事件并向上遍历可视化树以查找 ListBoxItem 对象,并将其 Selected 值设置为 true 的控件。

Put this in your ListBox.Resources

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>

And this in the Code Behind

protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
    ListBoxItem item = (ListBoxItem)sender;
    item.IsSelected = true;
}

You could use the following code as well which doesn't use code-behind, however it only keeps the ListBoxItem selected for as long as it has KeyBoard focus. Once focus leaves, the item becomes unselected

<Style TargetType="ListBoxItem">
  <Style.Triggers>
    <Trigger Property="IsKeyboardFocusWithin" Value="True">
      <Setter Property="IsSelected" Value="True" />
    </Trigger>
  </Style.Triggers>
</Style>

EDIT

Since Silverlight doesn't have EventSetters, you can use the ListBox's Loaded event and add the following to your code behind:

private void ResultListBox_Loaded(object sender, RoutedEventArgs e)
{
    ListBox list = (ListBox)sender;
    list.GotFocus += ResultListBox_GotFocus;
}

void ResultListBox_GotFocus(object sender, RoutedEventArgs e)
{
    var item = FindAncester<ListBoxItem>((DependencyObject)e.OriginalSource);
    if (item != null) item.IsSelected = true;
}

T FindAncester<T>(DependencyObject current) 
    where T : DependencyObject
{
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}

This captures the Focus event for the ListBox, takes the control that triggered the focus event and traverses up the visual tree to find the ListBoxItem objects, and sets it's Selected value to true.

狼亦尘 2024-12-06 09:49:04

雷切尔的解决方案效果很好。我在这种方法中发现的一个问题是,它确实将注意力集中在所选项目上。因此,用户需要在控件内双击才能将焦点放在其他项目上,例如可选择的文本或其他按钮。经过更多处理后,我发现您还可以通过将列表框所选项目设置为您单击的对象的数据上下文等来解决此问题。这很有效,允许您将其设置为控件内的任何 UI 对象。

   ListBox.SelectedItem = ((HyperlinkButton)sender).DataContext;

在此示例中,我在数据模板中有超链接按钮。单击它们会将焦点设置到选定的列表框项目。

Rachel's solution works great. The one issue I did find in this approach was that it does place total focus on the selected item. As a result the user would be required to double click within the control to place focus on other items such as selectable text or other button. After working with this a bit more I discovered you can also resolve this by setting the listbox selected items to the data context of the object you are clicking on etc. This works well as allows you to set this to any UI object within the control.

   ListBox.SelectedItem = ((HyperlinkButton)sender).DataContext;

In this example I had Hyperlink buttons within the data template. Clicking on them would then set the focus to the selected listbox item.

千寻… 2024-12-06 09:49:04

rlcrews 做对了!使用数据上下文:

ObservableCollection<Employee> employees1;
...
listBox1.ItemsSource = employees1;
...

//DataTemplate in ListBox has a button with following event
private void bnPromoteEmployee_Click(object sender, RoutedEventArgs e)
{
  Employee emp1 = (Employee)((Button)sender).DataContext;
  emp1.Promote();
}

rlcrews got it right! Use DataContext:

ObservableCollection<Employee> employees1;
...
listBox1.ItemsSource = employees1;
...

//DataTemplate in ListBox has a button with following event
private void bnPromoteEmployee_Click(object sender, RoutedEventArgs e)
{
  Employee emp1 = (Employee)((Button)sender).DataContext;
  emp1.Promote();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文