WPF,防止所选项目的状态发生变化

时间:2019-01-14 05:08:07

标签: wpf listview mvvm

我有一个类似的列表视图:

<ListView Name="ListViewItems" Grid.Row="2" Foreground="White" ItemsSource="{Binding Items}" 
                SelectedItem="{Binding CurrentSelectedItem ,Mode=TwoWay}" 
                ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionMode="Single" 
                HorizontalContentAlignment="Stretch" 
                ScrollViewer.VerticalScrollBarVisibility="Auto"  
                VerticalAlignment="Stretch" BorderThickness="0" >

    <ListView.ItemTemplate>
        <DataTemplate >
            <Grid  >
                <Grid.RowDefinitions>
                    <RowDefinition Height="25"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.5*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Label Grid.Column="0" Width="0" Visibility="Collapsed" Content="{Binding Id}"/>
                <Label Grid.Column="0"  Content="{Binding Name}" HorizontalContentAlignment="Left" Foreground="White" FontWeight="Bold" Background="Transparent"/>
                <Label Grid.Column="1"  Content="{Binding Provider}" HorizontalContentAlignment="Left" Foreground="White" Background="Transparent"/>
                <Label Grid.Column="0" Grid.ColumnSpan="2" Background="Transparent"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

当我更改所选项目(通过单击另一个列表视图项目)时,似乎会调用set中的CurrentSelectedItem

private MyObject _currentSelectedItem;
public MyObject CurrentSelectedItem
{
    get => _currentSelectedItem;
    set
    {
        if (Condition) 
        {
            // here i want to have previous item seleced
            // Currently i do nothing here
        }
        else
        {
            _currentSelectedItem = value;
        }
    }
}

如果Condition为真(如果我什么也不做),则CurrentSelectedItem将具有上一个值,这就是我想要的值, BUT 在用户界面中选中的项目(突出显示的项目)是我最近选择的项目。

我想要的是防止UI中出现此类行为。我的意思是CurrentSelectedItem并没有改变界面,而是改变了。

有什么办法可以防止这种行为?预先感谢。

解决方案:
作为@ Zeb-ur-Rehman,我们应该将先前的状态保存在_previousSelectedItem中。但是在else语句中,当我同时value提到当前对象和先前对象时,我没有将_currentSelectedItem分配给_currentSelectedItem = _previousSelectedItem。因此OnPropertyChanged将不会更新绑定的视图。

顺便说一句,我能以某种方式管理这种情况的唯一方法是将_currentSelectedMap保存在以前的版本中,并通过_currentSelectedMap = null更新UI,然后在稍作延迟(应该是延迟)之后进行更新用户界面通过保存的值是这样的:

if (Condition) 
{
    _previousSelectedItem = _currentSelectedItem;
    _currentSelectedItem = null;
    NotifyOfPropertyChange(()=> CurrentSelectedItem);
    Task.Delay(100).ContinueWith(x =>
    {
        Application.Current.Dispatcher.Invoke(() =>
            {
                _currentSelectedItem = _previousSelectedItem;
                NotifyOfPropertyChange(()=> CurrentSelectedItem);
            });
    });
}
else
{
    _currentSelectedItem = value;
}

1 个答案:

答案 0 :(得分:1)

这是您在属性设置器中需要做的事情。

private MyObject _previousSelectedItem;
private MyObject _currentSelectedItem;
public MyObject CurrentSelectedItem
{
    get => _currentSelectedItem;
    set
    {
        if (Condition) 
        {
            _previousSelectedItem = _currentSelectedItem;
            _currentSelectedItem = value;
        }
        else
        {
            _currentSelectedItem = _previousSelectedItem;
        }

        NotifyOfPropertyChange(()=> CurrentSelectedItem);
    }
}

您需要跟踪更改currentSelectedItem时可以捕获的先前值。下次如果条件不成立,则只需为您的currentSelecteditem分配上一个值即可。

希望它对您有用。

修改: 我没有提到您需要NotifyOfPropertyChange(()=> CurrentSelectedItem);因为我认为这太明显了。您的代码也应以这种方式工作。在Dispatcher中更改值的建议,因为值已经是2种方式绑定到控件。这就是WPF绑定的力量。