Silverlight如何在使用datatemplates中的按钮时提升listbox的选定项

Silverlight如何在使用datatemplates中的按钮时提升listbox的选定项,silverlight,mvvm,listbox,datatemplate,Silverlight,Mvvm,Listbox,Datatemplate,在Listbox控件中,我有一个由文本和按钮组成的数据模板。鉴于Silverlight/WPF的性质,当我单击listbox项中的按钮时,按钮事件在选择listbox项之前被捕获。因此,如果我试图传递所选列表框项目的记录ID,我当前只能通过先单击并选择列表框项目,然后单击按钮来传递 是否有办法提升listbox项目的选择,以便在创建listbox项目时,我能够单击listbox项目内的按钮,并调用一些事件(selectionChanged?),允许我捕获所选记录id并将其用于某些其他操作(在方法

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

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

listbox控件显示为:

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

在datatemplate(用户控件)中,按钮与许多其他字段一起驻留。除非有人要求,否则我将暂时省略该代码


提前谢谢

将其放入您的
列表框中。参考资料

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
您也可以使用下面的代码,它不使用代码隐藏,但是只要ListBoxItem具有键盘焦点,它就会保持选中状态。焦点离开后,该项目将被取消选中

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

编辑

由于Silverlight没有EventSetter,因此可以使用ListBox的已加载事件,并将以下内容添加到代码中:

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;
}
private void ResultListBox\u已加载(对象发送方、路由目标方)
{
列表框列表=(列表框)发送方;
list.GotFocus+=ResultListBox\u GotFocus;
}
void ResultListBox\u GotFocus(对象发送方,路由目标)
{
var项=FindAncester((DependencyObject)e.OriginalSource);
如果(item!=null)item.IsSelected=true;
}
T FindAncester(依赖对象当前)
其中T:DependencyObject
{
当前=VisualTreeHelper.GetParent(当前);
while(当前!=null)
{
如果(电流为T)
{
返回(T)电流;
}
当前=VisualTreeHelper.GetParent(当前);
};
返回null;
}

这将捕获列表框的焦点事件,获取触发焦点事件的控件,并向上遍历可视化树以查找
ListBoxItem
对象,并将其选定值设置为true。

将其放入
列表框。参考资料

<Style TargetType="{x:Type ListBoxItem}">
    <EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
您也可以使用下面的代码,它不使用代码隐藏,但是只要ListBoxItem具有键盘焦点,它就会保持选中状态。焦点离开后,该项目将被取消选中

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

编辑

由于Silverlight没有EventSetter,因此可以使用ListBox的已加载事件,并将以下内容添加到代码中:

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;
}
private void ResultListBox\u已加载(对象发送方、路由目标方)
{
列表框列表=(列表框)发送方;
list.GotFocus+=ResultListBox\u GotFocus;
}
void ResultListBox\u GotFocus(对象发送方,路由目标)
{
var项=FindAncester((DependencyObject)e.OriginalSource);
如果(item!=null)item.IsSelected=true;
}
T FindAncester(依赖对象当前)
其中T:DependencyObject
{
当前=VisualTreeHelper.GetParent(当前);
while(当前!=null)
{
如果(电流为T)
{
返回(T)电流;
}
当前=VisualTreeHelper.GetParent(当前);
};
返回null;
}

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

Rachel的解决方案非常有效。我在这种方法中发现的一个问题是,它确实将全部注意力放在所选项目上。因此,用户需要在控件内双击以将焦点放在其他项目上,例如可选文本或其他按钮。在进一步处理这个问题之后,我发现您还可以通过将listbox所选项目设置为您正在单击的对象的数据上下文等来解决此问题。这很好地工作,并允许您将其设置为控件中的任何UI对象

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

在本例中,我在数据模板中使用了超链接按钮。单击它们会将焦点设置为选定的列表框项目

Rachel的解决方案非常有效。我在这种方法中发现的一个问题是,它确实将全部注意力放在所选项目上。因此,用户需要在控件内双击以将焦点放在其他项目上,例如可选文本或其他按钮。在进一步处理这个问题之后,我发现您还可以通过将listbox所选项目设置为您正在单击的对象的数据上下文等来解决此问题。这很好地工作,并允许您将其设置为控件中的任何UI对象

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

在本例中,我在数据模板中使用了超链接按钮。单击它们会将焦点设置为选定的列表框项目

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

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();
}
observedcollection员工1;
...
listBox1.ItemsSource=员工1;
...
//ListBox中的DataTemplate有一个包含以下事件的按钮
私有无效BNPromoteTemployee_单击(对象发件人,路由收件人)