我有一个ListView
<ListView x:Name="BlockList" Grid.Row="1" Grid.ColumnSpan="4" ItemsSource="{Binding Blocks}">
<ListView.View>
<GridView>
<GridViewColumn Width="75" Header="Address" DisplayMemberBinding="{Binding Path=Address, Converter={StaticResource IntToHexConverter}}"/>
<GridViewColumn Width="100" Header="Length" DisplayMemberBinding="{Binding Length}"/>
<GridViewColumn Width="100" Header="Status" DisplayMemberBinding="{Binding Status}"/>
</GridView>
</ListView.View>
</ListView>
显示 Blocks
的 ObservableCollection
的地址、长度和状态。
public class Block : ObservableObject
{
public enum BlockStatus
{
Unwritten,
Written,
Verified,
Bad,
}
private UInt16 address;
public UInt16 Address
{
get { return address; }
set { address = value; NotifyPropertyChanged(); }
}
private byte[] data;
public byte[] Data
{
get { return data; }
set { data = value; NotifyPropertyChanged(); }
}
private BlockStatus status;
public BlockStatus Status
{
get { return status; }
set { status = value; NotifyPropertyChanged(); }
}
public UInt16 Length
{
get { return (UInt16)Data.Length; }
}
public Block(UInt16 address, byte[] data) : this(address, data, BlockStatus.Unwritten) { }
public Block(UInt16 address, byte[] data, BlockStatus status)
{
this.Address = address;
this.Data = data;
this.Status = status;
}
}
这些Blocks
最初将处于BlockStatus.Unwritten
状态,最终是Written
,然后是Verified
.当 Status
发生变化时,如何将 ListView
滚动到 Block
?
最佳答案
有很多事情需要完成。
1) 你的Block
需要实现INotifyPropertyChanged
public class Block : ObservableObject, INotifyPropertyChanged
{
// Your existing members and code
private BlockStatus _status;
public BlockStatus Status
{
get { return _status; }
set { _status = value; NotifyPropertyChanged("Status"); }
}
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2) 你的 ViewModel
需要有一个 StatusChanged
事件
public delegate void StatusChangedHandler(object sender, StatusChangedHandlerArgs args);
public event StatusChangedHandler StatusChanged;
// Put this class where it suits your project
public class StatusChangedHandlerArgs
{
public Block.BlockStatus NewStatus { get; private set; }
public StatusChangedHandlerArgs(Block.BlockStatus newStatus)
{
NewStatus = newStatus;
}
}
3) ViewModel
中的 Blocks
属性需要如下所示:
private ObservableCollection<Block> _blocks;
public ObservableCollection<Block> Blocks
{
get
{
return _blocks;
}
set
{
_blocks = value;
if (_blocks != null)
{
foreach (var block in _blocks)
{
block.PropertyChanged += block_PropertyChanged;
}
}
NotifyPropertyChanged("Blocks");
}
}
// The event handler for PropertyChanged
private void block_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName != "Status" || StatusChanged == null)
{
return;
}
var block = sender as Block;
if (block != null)
{
StatusChanged.Invoke(block, new StatusChangedHandlerArgs(block.Status));
}
}
4) 最后,您的 View
(它有一个 ViewModel
的实例)应该订阅后面代码中的 StatusChanged
事件。
// Somewhere in the initializer or constructor for the page
yourViewModel.StatusChanged += yourViewModel_StatusChanged;
// The handler for StatusChanged
private void yourViewModel_StatusChanged(object sender, StatusChangedHandlerArgs args)
{
var block = sender as Block;
if (block != null)
{
BlockList.ScrollIntoView(block);
}
}
关于C# 将 ListView 滚动到更新的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31867131/