C# 将 ListView 滚动到更新的项目

标签 c# wpf

我有一个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>

显示 BlocksObservableCollection 的地址、长度和状态。

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

Example Window

最佳答案

有很多事情需要完成。

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/

相关文章:

c# - 在 .NET 中更好地处理 404

c# - 模拟对象的属性以返回来自对象本身的值

c# - C# 中的西里尔编码

c# - 设置通用 WPF 控件的样式

wpf - 更改 WPF 项目模板的命名空间

c# - WPF ListView/GridView 单选bug

c# - 如何解析会导致非法 C# 标识符的 JSON 字符串?

.net - WPF:在一个窗口中管理多个用户控件

c# - 在 WPF 表单上显示 HTML 片段

.net - 什么是 MVVM 限制?