我有一个ListBox控件的情况。在项目模板中有一个按钮。当我单击按钮时,我想要选择所述ListBox的项目以更改为按钮所在的项目。此时,我可以通过单击项目模板中的其他位置来更改所选项目,但如果我选择该项目则不起作用按钮。为了澄清评论者的最后一句话,如果单击非按钮的项目模板,SelectedItem将按预期更改。如果单击项模板中的按钮,SelectedItem将不会更改。
更多信息:我正在使用MVVM,并且按钮已在视图模型中附加了一个命令。任何解决方案都需要允许它继续工作。
ListBox链接到ItemSource,ListBox的SelectedItem绑定到视图模型中的属性。
如果有一套方法可以做到这一点,我到目前为止一直无法找到它。
我正在使用C#和Visual Studio 2010.
感谢。
答案 0 :(得分:1)
如果您可以使用ToggleButton
并将IsChecked
绑定到ListBoxItem
IsSelected
属性,那就没问题了。
原因是因为未选择ListBoxItem
是因为Button正在处理MouseDown
事件,因此ListBoxItem
不知道点击。在您的按钮中为Click
创建一个事件处理程序并设置e.Handled = false;
。
答案 1 :(得分:1)
您的一些代码会有所帮助,但这是一个虚拟示例,说明如何通过MVVM模式单击按钮来选择ListBoxItem
。
public class MyViewModel : BaseViewModel // implements INotifyPropertyChanged
{
private ICommand _myCommand;
public ICommand MyCommand { get {return _myCommand;} private set { _myCommand = value; OnPropertyChanged(); }}
private ObservableCollection<int> _myObjects;
public ObservableCollection<int> MyObjects { get {return _myObjects;} private set {_myObjects = value; OnPropertyChanged();}}
private int _mySelectedObject;
public int MySelectedObject { get {return _mySelectedObject;} set {_mySelectedObject = value; OnPropertyChanged(); }}
public MyViewModel
{
MyCommand = new RelayCommand(SetSelectedObject); // the source code for RelayCommand may be found online.
}
private void SetSelectedObject(object obj)
{
int myInt = (int)obj;
MySelectedObject = myInt;
}
}
为了保持简单,已删除了一些XAML部件。不要简单地复制/粘贴此代码段,使其适应您的代码。
<UserControl x:Name="root" DataContext="{Binding MyViewModel, Source={StaticResource Locator.MyViewModel}}">
<ListBox ItemsSource="{Binding MyObjects}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding }"/>
<Button Command="{Binding MyCommand, ElementName=root}" CommandParameter="{Binding }"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
我还没有测试过这段代码。所以可能会有一些错误。不要犹豫,指出这些,我会更新我的代码。
编辑:以下是我的RelayCommand实现的源代码(从Telerik修改):
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action<object> _methodToExecute;
private Func<object, bool> _canExecuteEvaluator;
public RelayCommand(Action<object> methodToExecute, Func<object, bool> canExecuteEvaluator)
{
_methodToExecute = methodToExecute;
_canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action<object> methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (_canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = _canExecuteEvaluator.Invoke(parameter);
return result;
}
}
public void Execute(object parameter)
{
_umethodToExecute.Invoke(parameter);
}
}
答案 2 :(得分:0)
使用此功能,您可以获取作为按钮父级的列表框:
Function GetParent(child As UIElement, parentType As Type) As UIElement
If child Is Nothing Then Return Nothing
Dim p = child
Do
p = TryCast(VisualTreeHelper.GetParent(p), UIElement)
If p Is Nothing Then Return Nothing
If p.GetType Is parentType Then Return p
Loop
End Function
这是选择项目的代码。将其添加到按钮的Click事件:
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim lst As ListBox = GetParent(sender, GetType(ListBox))
lst.SelectedIndex = lst.Items.IndexOf(Me.DataContext)
End Sub
答案 3 :(得分:0)
C# 版本:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button b = sender as Button;
TListBoxItems data = b.DataContext as TListBoxItems;
ListBox aLB = new ListBox();
aLB = (ListBox)GetParent(sender, aLB.GetType());
aLB.SelectedIndex = aLB.Items.IndexOf(data);
}
public object GetParent(object child, Type parentType)
{
if (child == null)
return null/* TODO Change to default(_) if this is not a reference type */;
var p = child;
do
{
p = VisualTreeHelper.GetParent((UIElement)p) as UIElement;
if (p == null)
return null/* TODO Change to default(_) if this is not a reference type */;
if (p.GetType() == parentType)
return p;
}
while (true);
}