سؤال

لقد قمت بتنفيذ نمط اختيار مماثل لموقع واحد الموصوف فيه هذا المشنور باستخدام ViewModel لتخزين القيمة التي تم إرسالها، وبين ملزمة ListViewItem.IsSelected إلى ViewModel تم إرسالها:

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
    </Style>
</ListView.ItemContainerStyle>

إنه يعمل بشكل عام، لكنني واجه مشكلة شديدة. باستخدام A VirtualizingStackPanel كوحة في عرض القائمة، فقط المرئي ListViewItem يتم إنشاؤها. إذا كنت تستخدم "CTRL + A" لتحديد جميع العناصر، أو باستخدام تركيبة الاختصار مثل "SHIFT + CTRL + END" في العنصر الأول، فحصل جميع العناصر، ولكن بالنسبة للعناصر غير المرئية، لا يتم عرض ViewModel الخاص به تعيين إلى True. هذا منطقي، لأنه إذا كان ListViewItem لا يتم إنشاؤها، لا يمكن ربط الربط.

واجه أي شخص نفس المشكلة، ووجد حلا (بصرف النظر عن عدم استخدام VirtualizingStackPanel)?

هل كانت مفيدة؟

المحلول

لقد وجدت وسيلة أخرى من التحديد في نمط MVVM، والتي حل مشكلاتي. بدلا من الحفاظ على التحديد في ViewModel، يتم استرداد التحديد من مربع ListView / Listbox، ومرت كمعلمة إلى الأمر. كل ذلك في XAML:

<ListView 
    x:Name="_items"
    ItemsSource="{Binding Items}" ... />

<Button 
    Content="Remove Selected" 
    Command="{Binding RemoveSelectedItemsCommand}" 
    CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/>

في رأيي:

private void RemoveSelection(object parameter)
{
    IList selection = (IList)parameter;
    ...
}

نصائح أخرى

في حالتي، انتهى بي الأمر إلى حل هذا عن طريق اشتقاق فئة ListBoxex من مربع ListBox، وإضافة التعليمات البرمجية للرد على تغييرات التحديد، وفرض حالة التحديد على نماذج عرض العنصر:

private readonly List<IListItemViewModelBase> selectedItems = new List<IListItemViewModelBase>();

protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
    base.OnSelectionChanged(e);

    bool isVirtualizing = VirtualizingStackPanel.GetIsVirtualizing(this);
    bool isMultiSelect = (SelectionMode != SelectionMode.Single);

    if (isVirtualizing && isMultiSelect)
    {
        var newSelectedItems = SelectedItems.Cast<IListItemViewModelBase>();

        foreach (var deselectedItem in this.selectedItems.Except(newSelectedItems))
        {
            deselectedItem.IsSelected = false;
        }

        this.selectedItems.Clear();
        this.selectedItems.AddRange(newSelectedItems);

        foreach (var newlySelectedItem in this.selectedItems)
        {
            newlySelectedItem.IsSelected = true;
        }
    }
}

بصرف النظر عن عدم استخدام VirtualizingStackPanel, ، الشيء الوحيد الذي يمكنني التفكير فيه هو التقاط اختصارات لوحة المفاتيح هذه ولها أساليب لتعديل مجموعة معينة من ViewModel البنود بحيث IsSelected تم ضبط الخاصية على True (على سبيل المثال، SelectAll(), SelectFromCurrentToEnd()). تجاوز أساسا Binding تشغيل ListViewItem للسيطرة على اختيار هذه الحالات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top