XAML Переключить видимость ListViewItem при нажатии - PullRequest
0 голосов
/ 20 сентября 2019

Я пытаюсь изменить видимость элементов на основе выбранного ListViewItem.В основном каждый столбец в ListView имеет два элемента в сетке, метку и элемент управления (Combobox, DatePicker, Textbox и т. Д.).Если выбран ListViewItem, то я хочу, чтобы все элементы управления в этой строке были видны, иначе должна быть видна метка.Это в UserControl, а не в Window, если это имеет какое-то значение.

Вот моя модель представления

    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>

Любая идея, как заставить это работать, или естьлучший способ добиться того, чего я пытаюсь достичь?Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 20 сентября 2019

Правильный способ обновления SelectedLog - создать ItemContainerStyle для ListView и связать его там.Это правильное решение.Вам нужно будет сделать вашу модель представления предметом фактической модели представления, которая реализует INotifyPropertyChanged.Таким образом, изменение этого свойства никогда не повлияет на пользовательский интерфейс, поскольку пользовательский интерфейс не уведомляется об изменениях.Это решение следует.

Но если для модели представления не особенно важно, выбрана ли она, мы можем удалить ваш обработчик SelectionChanged, удалить SelectedLog из класса элемента и связать непосредственно с фактическим свойством IsSelected объекта ListViewItem в наших триггерах.Обратите внимание, что вы устанавливаете 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...