嗨,我是WPF的新手,我正在努力学习它。所以现在我想知道如何在ListBox中的文本块上创建onclick效果。我想点击listBox中的任何项目并打开一个新窗口。我一定是做错了什么但我不知道它是什么。到目前为止,我有以下内容。
<Grid>
<ItemsControl ItemsSource="{Binding Source={StaticResource cvsRoutes}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Name}" MinHeight="50">
<ListBox>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBox_MouseLeftButtonDown" />
<TextBlock Text="Something" >
<TextBlock.InputBindings>
<MouseBinding Command="" MouseAction="LeftClick" />
</TextBlock.InputBindings>
</TextBlock>
<TextBlock Text="Something" />
<TextBlock Text="Something" />
<TextBlock Text="Something" />
<TextBlock Text="Something" />
</ListBox>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
上面的代码在我的XAML文件中。如果是这样,我还需要其他东西。它应该在哪里?
答案 0 :(得分:3)
这是MVVM警察! ;)
Xaml:使用绑定到ICommand而不是System.Windows.Interactivity&amp; forinstance galasoft mvvm light。 我没有测试过下面的代码,我只是用记事本++编写了它。我现在看到一件事情,你是在一个数据模板&amp; listboxitem ...你的TextBlock会在LI而不是VM上查找命令,所以你需要一个时髦的绑定。检查它是否有效,但是您希望您的click事件在vm的datacontext上执行,而不是在listbox项上执行,因此必须稍微更改绑定(vacation ... =)) 列表框中的项目包装在ListBoxItems中,datacontext设置为LI应该呈现的内容,即列表中的项目。
您可能想要更改frpm
下面的KeyUp绑定<command:EventToCommand Command="{Binding KeyUpCommand}" PassEventArgsToCommand="True"/>
要:
<command:EventToCommand Command="{Binding Path=DataContext.KeyUpCommandCommand, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}}" PassEventArgsToCommand="True"/>
确保将UserControl替换为您的控件/页面/ cust ctrl / window的名称。
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:command="http://www.galasoft.ch/mvvmlight"
xmlns:local="clr-namespace:YOURNAMSPACE"
...
<UserControl.DataContext>
<local:ViewModelListStuff/>
</UserControl.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Source={StaticResource cvsRoutes}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Name}" MinHeight="50">
<ListBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<command:EventToCommand Command="{Binding PreviewMouseLeftButtonDownCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock Text="Something" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<command:EventToCommand Command="{Binding KeyUpCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<TextBlock Text="Something" />
<TextBlock Text="Something" />
<TextBlock Text="Something" />
<TextBlock Text="Something" />
</ListBox>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
现在您将需要一个viewmodel,您将其设置为datacontext。这是一个简单基类的例子(扩展由galasoft提供的ViewModelBase以增加功能是很好的。
VM baseclass(简化):
public class SomeBaseClass : INotifyPropertyChanged
{
// Other common functionality goes here..
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]// Commment out if your don't have R#
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
VM:
public class ViewModelListStuff : SomeBaseClass
{
private string name;
public ICommand PreviewMouseLeftButtonDownCommand { get; set; }
public ICommand KeyUpCommand { get; set; }
public String Name
{
get { return name; }
set
{
if (value == name) return;
name = value;
OnPropertyChanged();
}
}
// I would have exposed your cvsSomething here as a property instead, whatever it is.
public ViewModelListStuff()
{
InitStuff();
}
public void InitStuff()
{
PreviewMouseLeftButtonDownCommand = new RelayCommand<MouseButtonEventArgs>(PreviewMouseLeftButtonDown);
KeyUpCommandnCommand = new RelayCommand<KeyEventArgs>(KeyUp);
}
private void KeyUp(KeyEventArgs e)
{
// Do your stuff here...
}
private void PreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
// Do your stuff heere
}
}
希望它有所帮助!在我们将由命令调用的方法中创建断点,并观察命令方法的输出和堆栈跟踪。
干杯
了Stian