多选ListBox绑定问题

时间:2014-09-24 12:43:39

标签: c# wpf xaml listbox wpf-controls

我已经创建了一个从ListBox派生的自定义控件,我在获取" SelectedItemsList"在视图模型中绑定它的相应属性。

问题:列表框中的选定项目不会使其成为视图模型中绑定的属性。列表框允许多个选择,但这些选择都不会进入视图模型中的列表。

MultiSelectListBox:

public class MultiSelectListBox : ListBox
{
    public MultiSelectListBox() { }

    public static readonly DependencyProperty SelectedItemsListProperty =
        DependencyProperty.Register(
            "SelectedItemsList", 
            typeof(IList), 
            typeof(MultiSelectListBox),
            new PropertyMetadata(default(IList)));
    public IList SelectedItemsList
    {
        get { return (IList) GetValue(SelectedItemsListProperty); }
        set { SetValue(SelectedItemsListProperty, value); }
    }
}
MainWindow.xaml中的

声明:

<local:MultiSelectListBox
    DataContext="{StaticResource viewModel}"
    DockPanel.Dock="Left"
    Visibility="{Binding IsThailandFinal, Converter={StaticResource BoolToVisConverter}, FallbackValue=Visible}"
    ItemsSource="{Binding SelectedOutputtapeList}"
    SelectionMode="Multiple"
    SelectedItemsList="{Binding SelectedOutputTapes, Mode=TwoWay}"
    HorizontalAlignment="Right"
    Background="DeepSkyBlue"
    Foreground="MidnightBlue"
    ScrollViewer.VerticalScrollBarVisibility="Visible"
    Height="100"
    Width="70"
    Margin="5"/>

查看模型(简化):

public class BTLogFrontEndViewModel : ViewModelBase
{
    private List<string> selectedOutputTapes;
    public BTLogFrontEndViewModel()
    {
        selectedOutputTapes = new List<string>();
    }
    public List<string> SelectedOutputTapes
    {
        get
        {
            return selectedOutputTapes;
        }
        set
        {
            selectedOutputTapes = value;
            OnPropertyChanged("SelectedOutputTapes");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

一种方法是不使用自定义ListBox并使用列表中扩展INotifyPropertyChanged的对象:

<ListBox
    Width="70"
    Height="100"
    HorizontalAlignment="Right"
    Margin="5"
    Background="DeepSkyBlue"
    DockPanel.Dock="Left"
    Foreground="MidnightBlue"
    ItemsSource="{Binding SelectedOutputtapeList}"
    ScrollViewer.VerticalScrollBarVisibility="Visible"
    SelectionMode="Multiple"
    DisplayMemberPath="Description"
    Visibility="{Binding IsThailandFinal, Converter={StaticResource BoolToVisConverter}, FallbackValue=Visible}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

假设BTLogFrontEndViewModel是您的DataContext:

public class BTLogFrontEndViewModel : ViewModelBase
{
    private ObservableCollection<OutputTapeViewModel> m_SelectedOutputtapeList;

    public ObservableCollection<OutputTapeViewModel> SelectedOutputtapeList
    {
        get
        {
            return m_SelectedOutputtapeList;
        }
        set
        {
           m_SelectedOutputtapeList = value;

           NotifyPropertyChanged("SelectedOutputtapeList");
        }
    }
}

其中OutputTapeViewModel声明为:

public class OutputTapeViewModel : ViewModelBase
{
    private string m_Description;

    public string Description
    {
        get
        {
            return m_Description;
        }
        set
        {
            m_Description = value;

            NotifyPropertyChanged("Description");
        }
    }

    private bool m_IsSelected;

    public string IsSelected
    {
        get
        {
            return m_IsSelected;
        }
        set
        {
            m_IsSelected = value;

            NotifyPropertyChanged("IsSelected");
        }
    }
}

需要注意的重要事项是在列表框中我添加了DisplayMemberPath属性,以便在OutputTapeViewModel类中使用description字段来显示列表框中的内容。它还有一个项容器样式,当在ListBox中选中时,它会绑定到OutputTapeViewModel.IsSelected属性。此OutputTapeViewModel.IsSelected允许您以下列方式使用BTLogFrontEndViewModel.SelectedOutputtapeList属性:

var selectedItems = SelectedOutputtapeList.Where(item => item.IsSelected);

这只适用于您的情况,如果您不关心执行LINQ表达式的开销。