隐藏WPF列表视图中的列表视图项

ltskdhd1  于 2023-03-09  发布在  其他
关注(0)|答案(7)|浏览(191)

如何在绑定的ListView中隐藏ListViewItem?注意:我不想把它拿掉。

xienkqul

xienkqul1#

是啊,这很简单。
你需要做的第一件事是给你绑定的类添加一个属性。例如,如果你绑定到一个带有FirstName和LastName的User类,只需添加一个布尔型的IsSupposedToShow属性(当然,你可以使用任何你喜欢的属性)。如下所示:

class User: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string FirstName { get; set; }
    public string LastName { get; set; }

    private bool m_IsSupposedToShow;
    public bool IsSupposedToShow
    {
        get { return m_IsSupposedToShow; }
        set
        {
            if (m_IsSupposedToShow == value)
                return;
            m_IsSupposedToShow = value;
            if (PropertyChanged != null)
                PropertyChanged(this, 
                    new PropertyChangedEventArgs("IsSupposedToShow"));
        }
    }
}

然后,记住,要隐藏某个项目,不要在UI中执行--不不不!在数据中执行。我的意思是,查找要隐藏的用户记录,并在后台更改其中的属性(就像在视图模型中一样)--让UI做出React。让XAML服从数据。
就像这样:

<DataTemplate DataType="{x:Type YourType}">
    <DataTemplate.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSupposedToShow}" Value="False">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataTemplate.Resources>
    <!-- your UI here -->
    <TextBlock> 
        <TextBlock.Text> 
        <MultiBinding StringFormat="{}{0}, {1}"> 
            <Binding Path="LastName" /> 
            <Binding Path="FirstName" /> 
        </MultiBinding> 
        </TextBlock.Text>
    </TextBlock>
</DataTemplate>

当您将IsSupposedToShow更改为false时,XAML会理解它应该更改整个DataTemplate的可见性。WPF已经为您准备好了,这就是您在问题中想要的!
祝你好运!

lhcgjxsq

lhcgjxsq2#

我会遵循的方法,从最可取到最不可取:

  • ListView.ItemContainerStyle中,使用DataTrigger根据绑定属性设置Visibility
  • 使用ItemTemplate中的样式,或者如果要从资源字典中获取默认模板,则使用DataTemplate中的样式。
  • ListViewItemsSource设置为CollectionView,并在代码隐藏中处理CollectionViewFilter事件。有关详细信息,请参见MSDN对集合视图的讨论。
  • 维护单独的ObservableCollection作为ListViewItemsSource,并根据需要添加/删除项目。

在任何情况下,我都不会使用ValueConverter,因为我对它们有一种可能是非理性的厌恶。
我认为使用CollectionView可能是最正确的方法,但它们有点不优雅,因为您必须编写事件处理程序来实现过滤。

bt1cpqcv

bt1cpqcv3#

使用带有触发器的样式将项目可见性设置为折叠。

r6vfmomb

r6vfmomb4#

这一页给了我所需要的答案:http://www.abhisheksur.com/2010/08/woring-with-icollectionviewsource-in.html(参见“滤波”部分。)
哇,比XAML简单多了。
示例:

bool myFilter(object obj)
{
    // Param 'obj' comes from your ObservableCollection<T>.
    MyClass c = obj as MyClass;
    return c.MyFilterTest();
}

// apply it
myListView.Items.Filter = myFilter;
// clear it
myListView.Items.Filter = null;
oo7oh9g9

oo7oh9g95#

ListView.ItemContainerStyle的方法

<ListView ItemsSource="{Binding Path=Messages}" Grid.Column="1" Grid.Row="1" x:Name="Messages"
          SelectedItem="{Binding Path=SelectedMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsVisible}" Value="False" >
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate >
        <DataTemplate>                    
            <StackPanel Orientation="Horizontal" >
                <TextBlock VerticalAlignment="Center" >
                    <TextBlock.Text>
                        <MultiBinding StringFormat="{}{0} => {1}">
                            <Binding Path="AuthorName" />
                            <Binding Path="ReceiverName"/>
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Jerry尼克松的回答对我来说并不完全有效。我必须稍微修改一下xaml。折叠的列表视图项在我使用DataTemplate.Resources时占用了很小的布局空间,

lpwwtiir

lpwwtiir6#

<ItemsControl>
 <ItemTemplate>
  <DataTemplate>
   <Image Visibility='{Binding Converter=my:MaybeHideThisElementConverter}' />
   </Image>
  </DataTemplate>
 </ItemTemplate>
</ItemsControl>

我们在这里所做的是将决策委托给MaybeHideThisElementConverter的实现。如果对象的User属性为null,或者Count为偶数,或者应用程序需要的任何自定义逻辑,则可以在此处返回Collapsed。转换器将逐个传递集合中的每个项。并且您可以根据具体情况返回Visibility.Collapsed或Visibility.Visible。

oug3syen

oug3syen7#

转换器和ListView.ItemContainerStyle的另一种方法,这一次使用Setter属性Visibility代替Data Triggers。如果您有复杂的业务逻辑来决定是否显示或折叠,我更喜欢这种方法。而且这种方法允许在多个屏幕上重用转换器。
下面是一个来自XAML的ListView代码片段。请记住用Rows替换列表:

<ListView ItemsSource="{Binding Rows}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Visibility" Value="{Binding ., Converter={StaticResource RowVisibilityConverter}}" />
            </Style>
        </ListView.ItemContainerStyle>
 </ListView>

下面是转换器代码段。请记住用Row替换类。:

public class RowVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Row row)
        {
            if (HideRow(row))
            {
                return Visibility.Collapsed;
            }
        }
        
        return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private static bool HideRow(Row row)
    {
        // TODO: Complex business logic that returns True or False
    }
}

记住要将转换器声明添加到App.xaml中,或者作为用户控件/窗口或ListView的资源添加,这样一切都连接起来了。

相关问题