【发布时间】:2018-09-18 20:03:09
【问题描述】:
我不知道如何在 ListView 中自动更改焦点项目。
当我将“IsSelected”属性更改为数据绑定列表中的其他元素时,我希望视图中的焦点项目能够自动更改:
当 PC/SC 读卡器修改项目时(将此视为输入),下一个元素应像这样聚焦:
我想留在 MVVM 中,因此在 ViewModel 中没有引用 View。以下是我当前的代码。
Model :主要目的是使用 IsSelected 属性扩展 DTO 并实现 INotifyPropertyChanged
public class SmartDeviceModel : INotifyPropertyChanged
{
public bool IsSelected;
private DtoReader _dtoReader;
public SmartDeviceModel(DtoReader _reader)
{
_dtoReader = _reader;
}
public string DisplayName => _dtoReader.DisplayName;
public string Uid
{
get
{
return _dtoReader.Uid;
}
set
{
_dtoReader.Uid = value;
OnPropertyChanged("Uid");
}
}
public long RadioId
{
get
{
return _dtoReader.RadioId : _dtoMarker.RadioId;
}
set
{
_dtoReader.RadioId = value;
OnPropertyChanged("RadioId");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
ViewModel 收到 PC/SC 读卡器的事件,以将来自 RFID 芯片的数据与当前选定的项目配对。当 RFID 芯片从 PC/SC Reader 中移除时,下一个元素被很好地选择但没有被聚焦。
public class ScanDeviceViewModel : BaseViewModel
{
public BindingList<SmartDeviceModel> ReaderList { get; }
public int SelectedReaderIndex;
private ITagReaderInput _rfidReader;
public ScanDeviceViewModel()
{
//Get Data listener for RFID Tag
_rfidReader = new IdentivTagReader.IdentivTagReader();
// Data Source of DTO
SiteInteractor siteInterractor = new SiteInteractor();
// List used for DataBinding
ReaderList = new BindingList<SmartDeviceModel>();
foreach (DtoReader m in SiteInteractor.GetReaders().OrderBy(x => x.DisplayName))
{
ReaderList.Add(new SmartDeviceModel(m));
}
if (ReaderList.Count() > 0)
{
for (var i = 0; i < ReaderList.Count(); i++)
{
if (String.IsNullOrEmpty(ReaderList[i].Uid))
{
SelectedReaderIndex = i;
ReaderList[i].IsSelected = true;
break;
}
}
}
_rfidReader.LabelDetected += RfidTagDetected;
_rfidReader.LabelRemoved += RfidRemoved;
}
private void RfidTagDetected(ITagLabel tag)
{
if (ReaderList[SelectedReaderIndex] != null && string.IsNullOrEmpty(ReaderList[SelectedReaderIndex].Uid))
{
ReaderList[SelectedReaderIndex].IsSelected = true;
ReaderList[SelectedReaderIndex].Uid = tag.Uid;
ReaderList[SelectedReaderIndex].RadioId = tag.RadioId;
}
}
private void RfidRemoved(ITagLabel tag)
{
if (ReaderList[SelectedReaderIndex].Uid == tag.Uid)
{
ReaderList[SelectedReaderIndex].IsSelected = false;
while (ReaderList.Count >= SelectedReaderIndex + 1)
{
SelectedReaderIndex++;
if (String.IsNullOrEmpty(ReaderList[SelectedReaderIndex].Uid)){
ReaderList[SelectedReaderIndex].IsSelected = true;
break;
}
}
}
}
}
查看我正在使用“Setter”,按照here 的建议,将数据绑定到我的模型属性“IsSelected”,但我最想念的还有一些我还不明白的东西。
<ListView ItemsSource="{Binding ReaderList}"
Margin="5" x:Name="listViewReader" SelectionMode="Single"
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox Grid.Row ="0" Stretch="Uniform" HorizontalAlignment="Left" VerticalAlignment="Bottom" MaxHeight="90">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Content="{Binding DisplayName}" />
<DockPanel Grid.Row="1">
<Label Content="UID"/>
<Label Content="{Binding Uid}"/>
</DockPanel>
<DockPanel Grid.Row="1" Grid.Column="1">
<Label Content="RadioID" />
<Label Content="{Binding RadioId}"/>
</DockPanel>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我尝试了几种方法like this answer,虽然项目选择得很好,但没有重点。
【问题讨论】:
-
根据您的集合的默认视图绑定到 listcollectionview。 Set 与列表视图上的当前项目同步,因此当前项目将是选定的项目,反之亦然。添加一个关注所选项目的行为。谷歌,你会发现它很容易。这是一个数据网格,但数据网格和列表视图都是项目控件。 social.technet.microsoft.com/wiki/contents/articles/…
-
@Andy :ListCollectionView 看起来很有希望,我会马上试一试。感谢您为我指明正确的方向
标签: wpf