繁体   English   中英

XAML 单击时切换 ListViewItem 可见性

[英]XAML Toggle ListViewItem visibility on click

我正在尝试根据所选的 ListViewItem 更改项目的可见性。 基本上,ListView 中的每一列在网格上都有两个项目,一个 label 和一个控件(Combobox、DatePicker、Textbox 等)。 如果选择了 ListViewItem,那么我希望该行中的所有控件都可见,否则 label 应该可见。 这是在 UserControl 上,而不是 Window,如果这有什么不同的话。

这是我的看法 model

    public class DailyServiceLogsViewModel
{ 
    public int DailyServiceLogID { get; set; }
    public int EmployeePositionID { get; set; }
    public PositionType SelectedEmployeePosition { get; set; }
    public List<PositionType> EmployeePositionList { get; set; }
    public List<EmployeeSelectionListViewModel> EmployeeList { get; set; }
    public EmployeeSelectionListViewModel SelectedEmployee { get; set; }
    public string EmployeeName { get; set; }
    public string PositionDescription { get; set; }
    public DateTime? Date { get; set; }
    public string WorkArea { get; set; }
    public bool SelectedLog { get; set; }
}

背后的代码

            private DBContext _dbContext= new DBContext();
            public ObservableCollection<DailyServiceLogsViewModel> DailyServiceLogs { get; set; }

            public void OnLoad()
            {
                _dbContext= new DBContext();
                List<EmployeeSelectionListViewModel> employeeList = _dbContext.Employees.Where(emp => emp.Active).Select(employee => new EmployeeSelectionListViewModel { EmployeeID = employee.EmployeeID, EmployeeName = employee.FirstName + " " + employee.LastName }).ToList();
                DailyServiceLogs = new ObservableCollection<DailyServiceLogsViewModel>();
                foreach (var serviceLog in _dbContext.DailyServiceLogs.Where(d => d.PayPeriodID == CurrentPayPeriod.PayPeriodID).OrderBy(d => d.EmployeePosition.Employee.LastName).ThenBy(d => d.EmployeePosition.Employee.FirstName))
                {
                    DailyServiceLogs.Add(new DailyServiceLogsViewModel
                    {
                        DailyServiceLogID = serviceLog.DailyServiceLogID,
                        EmployeePositionID = serviceLog.EmployeePositionID,
                        SelectedEmployeePosition = serviceLog.EmployeePosition.PositionType,
                        EmployeeName = serviceLog.EmployeePosition.Employee.FirstName + " " + serviceLog.EmployeePosition.Employee.LastName,
                        Date = serviceLog.Date,
                        PositionDescription = serviceLog.EmployeePosition.PositionType.Description,
                        WorkArea = serviceLog.Workarea,
                        EmployeeList = employeeList,
                        SelectedEmployee = new EmployeeSelectionListViewModel { EmployeeID = serviceLog.EmployeePosition.EmployeeID, EmployeeName = serviceLog.EmployeePosition.Employee.FirstName + " " + serviceLog.EmployeePosition.Employee.LastName },
                        EmployeePositionList = _dbContext.PositionTypes.Where(pt => pt.Active && _payrollContext.EmployeePositions.Any(ep => ep.EmployeeID == serviceLog.EmployeePosition.EmployeeID && ep.PositionTypeID == pt.PositionTypeID)).ToList(),
                        SelectedLog = false
                    });
                  }
                  ListViewTest.DataContext = this;
                  ListViewTest.ItemsSource = DailyServiceLogs;
                }

        private void DailyServiceLog_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!(sender is ListView senderListView)) return;
            if (senderListView.SelectedItem == null) return;

            if (senderListView.SelectedItem.GetType() == typeof(DailyServiceLogsViewModel))
            {
                foreach (var log in DailyServiceLogs)
                {
                    log.SelectedLog = log.DailyServiceLogID == ((DailyServiceLogsViewModel) senderListView.SelectedItem).DailyServiceLogID;
                }                    
            }
        }

我尝试过使用 DataTriggers,但我对它们不太熟悉

            <ListView Name="ListViewTest" Grid.Row="1" ItemsSource="{Binding}" SelectionChanged="DailyServiceLog_OnSelectionChanged">
                <ListView.View>
                    <GridView>
                        <GridViewColumn x:Name="clmServiceEmployeeName" Header="Employee" Width="155">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid x:Name="gdEmployee" Width="{Binding ElementName=clmServiceEmployeeName, Path=Width}" Tag="{Binding DailyServiceLogID}">
                                        <Label Content="{Binding EmployeeName}" >
                                            <Label.Style>
                                                <Style TargetType="{x:Type Label}">
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding SelectedItem.SelectedLog}" Value="True">
                                                            <Setter Property="Visibility" Value="Hidden"/>
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Label.Style>
                                        </Label>
                                        <ComboBox Tag="{Binding ElementName=gdEmployee, Path=Tag}" ItemsSource="{Binding EmployeeList}" SelectedValue="{Binding SelectedEmployee.EmployeeID}" DisplayMemberPath="EmployeeName" SelectedValuePath="EmployeeID" FlowDirection="LeftToRight" Margin="15,5" HorizontalAlignment="Stretch" >
                                            <ComboBox.Style>
                                                <Style TargetType="{x:Type ComboBox}">
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding SelectedItem.SelectedLog}" Value="True">
                                                            <Setter Property="Visibility" Value="Visible"/>
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </ComboBox.Style>
                                        </ComboBox>
                                    </Grid>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                     ...
                    </GridView>
                </ListView.View>
            </ListView>

我也试过用转换器

            <ListView Name="ListViewTest" Grid.Row="1" ItemsSource="{Binding}" SelectionChanged="DailyServiceLog_OnSelectionChanged">
                <ListView.View>
                    <GridView>
                        <GridViewColumn x:Name="clmServiceEmployeeName" Header="Employee" Width="155">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid x:Name="gdEmployee" Width="{Binding ElementName=clmServiceEmployeeName, Path=Width}" Tag="{Binding DailyServiceLogID}">
                                        <Grid.Resources>
                                            <dataconverter:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/>
                                            <dataconverter:InvertedBoolVisibilityConverter x:Key="InvertedBoolVisibilityConverter"/>
                                        </Grid.Resources>
                                        <Label Content="{Binding EmployeeName}" Visibility="{Binding ElementName=PayrollControl, Path=SelectedServiceLog, Converter={StaticResource InvertedBoolVisibilityConverter}}"/>
                                        <ComboBox Tag="{Binding ElementName=gdEmployee, Path=Tag}" ItemsSource="{Binding EmployeeList}" SelectedValue="{Binding SelectedEmployee.EmployeeID}" Visibility="{Binding SelectedServiceLog, Converter={StaticResource BoolVisibilityConverter}}" DisplayMemberPath="EmployeeName" SelectedValuePath="EmployeeID" FlowDirection="LeftToRight" Margin="15,5" HorizontalAlignment="Stretch"  />
                                    </Grid>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>

知道如何将其发送给 function,或者是否有更好的方法来了解我想要实现的目标? 任何帮助将不胜感激。

保持SelectedLog更新的正确方法是为 ListView 创建一个ItemContainerStyle ,并将其绑定到那里。 这才是正确的解决方案。 您需要使您的项目视图模型成为实现INotifyPropertyChanged的实际视图模型。 事实上,更改该属性永远不会影响 UI 中的任何内容,因为 UI 不会收到更改通知。 该解决方案如下。

但是,如果视图模型不特别关心它是否被选中,我们可以删除您的 SelectionChanged 处理程序,从项目 class 中删除SelectedLog ,并在我们的触发器中直接绑定到 ListViewItem 的实际 IsSelected 属性。 请注意,您将 ComboBox 设置为在选择项目时可见,但在未选择项目时您从未隐藏它。 我已经解决了。 当我们被选中时,一个控件被隐藏,当我们未被选中时,另一个控件被隐藏。

<Label Content="{Binding EmployeeName}" >
    <Label.Style>
        <Style TargetType="{x:Type Label}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}" Value="True">
                    <Setter Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Label.Style>
</Label>
<ComboBox Tag="{Binding ElementName=gdEmployee, Path=Tag}" ItemsSource="{Binding EmployeeList}" SelectedValue="{Binding SelectedEmployee.EmployeeID}" DisplayMemberPath="EmployeeName" SelectedValuePath="EmployeeID" FlowDirection="LeftToRight" Margin="15,5" HorizontalAlignment="Stretch" >
    <ComboBox.Style>
        <Style TargetType="{x:Type ComboBox}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}" Value="False">
                    <Setter Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.Style>
</ComboBox>

您应该学习如何创建和绑定视图模型属性,这就是解决方案。 首先,我们需要使“viewmodel”成为一个实际的 viewmodel:

public class DailyServiceLogsViewModel : ViewModelBase
{
    public int DailyServiceLogID { get; set; }
    public int EmployeePositionID { get; set; }
    public PositionType SelectedEmployeePosition { get; set; }
    public List<PositionType> EmployeePositionList { get; set; }
    public List<EmployeeSelectionListViewModel> EmployeeList { get; set; }
    public EmployeeSelectionListViewModel SelectedEmployee { get; set; }
    public string EmployeeName { get; set; }
    public string PositionDescription { get; set; }
    public DateTime? Date { get; set; }
    public string WorkArea { get; set; }

    //  Only properties like this will notify the UI when they update. 
    private bool _isSelectedLog = false;
    public bool IsSelectedLog
    {
        get => _isSelectedLog;
        set => SetProperty(ref _isSelectedLog, value);
    }
}

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));

    public void SetProperty<T>(ref T field, T value, [CallerMemberName] string propName = null)
    {
        if (!Object.Equals(field, value))
        {
            field = value;
            OnPropertyChanged(propName);
        }
    }
}

其次,添加一个 ItemContainerStyle,它在选择项目时设置IsSelectedLog 您可以删除 SelectionChanged 处理程序。

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelectedLog}" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn x:Name="clmServiceEmployeeName" Header="Employee" Width="155">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <Grid Tag="{Binding DailyServiceLogID}">
                            <Label Content="{Binding EmployeeName}" >
                                <Label.Style>
                                    <Style TargetType="{x:Type Label}">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding SelectedLog}" Value="True">
                                                <Setter Property="Visibility" Value="Hidden"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Label.Style>
                            </Label>
                            <ComboBox Tag="{Binding ElementName=gdEmployee, Path=Tag}" ItemsSource="{Binding EmployeeList}" SelectedValue="{Binding SelectedEmployee.EmployeeID}" DisplayMemberPath="EmployeeName" SelectedValuePath="EmployeeID" FlowDirection="LeftToRight" Margin="15,5" HorizontalAlignment="Stretch" >
                                <ComboBox.Style>
                                    <Style TargetType="{x:Type ComboBox}">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding SelectedLog}" Value="False">
                                                <Setter Property="Visibility" Value="Hidden"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </ComboBox.Style>
                            </ComboBox>
                        </Grid>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM