在ListBox(WP7)上将CommandParameter设置为当前点击的项

3
我可以帮您翻译。以下是翻译结果:

我想将命令参数设置为当前选定项的ListBox。

XAML:

<!--<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">-->
    <ListBox ItemsSource="{Binding Places}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Tap">
                <i:InvokeCommandAction Command="{Binding ListBoxClick}" CommandParameter="{Binding}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <ListBox.ItemTemplate>
            <DataTemplate>
                (...)
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

C#(暴露ListBoxClick命令的ViewModel代码部分)

public RelayCommand ListBoxClick { get; set; }

ListBoxClick = new RelayCommand((o) => {
    //model is always null
    var model = o as BasicModel;

    SelectedPlace = model;
});

我添加了适当的引用和命名空间:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

问题在于由RelayCommand对象调用的操作中,o参数始终为空。 更新 SelectedPlace属性的C#代码。
public BasicModel SelectedPlace {
            get {
                return _selectedPlace;
            }
            set {
                _selectedPlace = value;
                RaisePropertyChanged("SelectedPlace");
            }
        }

当我使用这个时:
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">

首次单击 ListBoxItem 时,所有内容都正常工作,但是当我单击所选的 ListBoxItem 时,什么也不会发生,因为选择并未更改。我需要能够在这两种情况下检测到项目点击。


Places 类型是 BasicModel 吗? - undefined
是的,Places 是一个 ObservableCollection<BasicModel> - undefined
请在对你的问题进行编辑时解释清楚你的具体需求是什么。暂时不要考虑ICommandSelectedItem,告诉我们你实际上想通过这个实现什么目标。 - undefined
我更新了我的问题。 - undefined
2个回答

0

试试这个:

<ListBox ItemsSource="{Binding Places}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Tap">
            <i:InvokeCommandAction Command="{Binding ListBoxClick}" 
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={
x:Type ListBox}}}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <ListBox.ItemTemplate>
        <DataTemplate>
            (...)
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

如果那样不起作用,试着将Binding更改为这个。
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"

更新 >>>

哦,抱歉,我没有注意到你正在使用Windows Phone 7。作为替代方案,尝试在你的代码后台/视图模型中添加一个绑定到 ListBox.SelectedItem 属性的属性:

<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedItem}" ... />

然后你应该能够做到这一点:
ListBoxClick = new RelayCommand(() => {
    SelectedPlace = SelectedItem;
});

更新 2 >>>

我不知道 Windows Phone 7 是否支持 Binding.ElementName 属性,但如果支持的话,请尝试这样做:

<ListBox Name="ListBox" ItemsSource="{Binding Places}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Tap">
            <i:InvokeCommandAction Command="{Binding ListBoxClick}" 
CommandParameter="{Binding SelectedItem, ElementNameListBox}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <ListBox.ItemTemplate>
        <DataTemplate>
            (...)
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

当我使用第二个解决方案时,o仍然为空,当我使用第一个解决方案时,我得到以下错误信息:在XML命名空间'http://schemas.microsoft.com/winfx/2006/xaml/presentation'中,类型'RelativeSource'上不存在属性'AncestorType'未找到类型'x:Type'。请确保您没有丢失程序集引用,并且所有引用的程序集都已构建。在类型'RelativeSource'中未找到属性'AncestorType'。我在此视图中使用的命名空间如下: - undefined
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" - undefined
我实际上有这个属性,它叫做SelectedPlace :). 也许我应该解释一下为什么我使用触发器而不是直接使用SelectedItem属性。如果我第一次点击ListBoxItem,后者的一切都正常工作,但是当我点击已选中的ListBoxItem时,什么都不会发生,因为选择没有改变。我需要能够在这两种情况下检测到项目的点击。 - undefined

0
我找到了一个不太好看的方法来实现我的目标。
XAML
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">

C#(视图模型)

private bool _placeSelected;

public BasicModel SelectedPlace {
    get {
        return _selectedPlace;
    }
    set {
        _placeSelected = true;
        _selectedPlace = value;
        RaisePropertyChanged("SelectedPlace");
    }
}

ListBoxClick = new RelayCommand((o) => {
    if (!_placeSelected) {
        SelectedPlace = _selectedPlace;
    }
    else {
        _placeSelected = false;
    }
});

这样 RaisePropertyChanged("SelectedPlace"); 会在两种情况下被调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接