简体   繁体   English

C#WPF Listview项目刷新在OnPropertyChanged之后不触发

[英]C# WPF Listview item refresh not firing after OnPropertyChanged

I created a view control to display data graphically. 我创建了一个视图控件以图形方式显示数据。 As there could be number of instances of the view, I used a ListView control and bound it to an observable collection of objects - Sheets. 由于可能有许多视图实例,因此我使用了ListView控件,并将其绑定到可观察到的对象集合-图纸。 Sheets is an observable collection of SheetContainer object which has sheet and a name. Sheets是SheetContainer对象的一个​​可观察的集合,该对象具有工作表和名称。 The viewer displays sheet. 查看器显示工作表。

The xaml for the listview looks like: 列表视图的xaml看起来像:

<ListView x:Name="ListViewSheetSlider" Height="170" Grid.Row="1" BorderThickness="0" 
                              ItemsSource="{Binding Sheets}" SelectionChanged="ListViewSheetSlider_SelectionChanged" >
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="{Binding Name}" />
                <Viewbox Width="150" Height="150">
                    <SheetViewer:Viewer SetSheet="{Binding MySheet, NotifyOnSourceUpdated=True}" />
                </Viewbox>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"></StackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

The SelectionChanged method looks like: SelectionChanged方法如下所示:

private void UpdateSheetAndSlider()
{
    workspace.Sheets[SelectedSheetIndex] = MySheetDesigner.Sheet;
    //   ((SheetContainer)ListViewSheetSlider.SelectedItem).MySheet = MySheetDesigner.Sheet;
    Sheets[SelectedSheetIndex].MySheet = MySheetDesigner.Sheet;
}


private void MySheetDesigner_SheetChanged(object sender, EventArgs e)
{
    UpdateSheetAndSlider();
}

private void ListViewSheetSlider_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int index = ListViewSheetSlider.SelectedIndex;

    UpdateSheetAndSlider();
    SelectedSheetIndex = index;
    MySheetDesigner.Sheet = workspace.Sheets[index];
    ListViewSheetSlider.UpdateLayout();
}

The SheetContainer implementation is simple. SheetContainer实现很简单。 It looks like: 看起来像:

public class SheetContainer : INotifyPropertyChanged
{
    public string Name { get; set; }

    private Sheet mySheet;
    public Sheet MySheet
    {
        get => mySheet;
        set
        {
            mySheet = value;

            OnPropertyChanged("MySheet");
        }
    }

    #region INotifyPropertyChanged Handler
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

}

The viewer xaml and codebehind look like: 查看器xaml和代码隐藏如下所示:

<UserControl x:Class="SheetViewer.Viewer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SheetViewer"
             xmlns:cad="clr-namespace:Cad;assembly=Cad"
             mc:Ignorable="d"        
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <cad:Cad
            x:Name="CadSurface" >
        </cad:Cad>
    </Grid>
</UserControl>

code behind: 后面的代码:

public partial class Viewer : UserControl
{

    public static readonly DependencyProperty SetSheetProperty =
             DependencyProperty.Register("SetSheet", typeof(Sheet), typeof(Viewer), new
                PropertyMetadata(default(Sheet), new PropertyChangedCallback(OnSetSheetChanged)));

    public Sheet SetSheet
    {
        get { return (Sheet)GetValue(SetSheetProperty); }
        set { SetValue(SetSheetProperty, value);}
    }

    private static void OnSetSheetChanged(DependencyObject d,
       DependencyPropertyChangedEventArgs e)
    {
        Viewer UserControl1Control = d as Viewer;
        UserControl1Control.OnSetSheetChanged(e);
    }

    private void OnSetSheetChanged(DependencyPropertyChangedEventArgs e)
    {
        //tbTest.Text = e.NewValue.ToString();
        Sheet s = (Sheet)e.NewValue;
        DrawSheet(s);
    }

    public Viewer()
    {
        InitializeComponent();
    }


    private void DrawSheet(Sheet sheet)
    {
        CadSurface.Draw();
    }

}

I expect the DrawSheet method to fire upon selection change in the listview. 我希望在列表视图中的选择更改时能够触发DrawSheet方法。 The property changed does get fired in SheetContainer, but does not propagate further to draw the sheet. 更改的属性的确在SheetContainer中触发,但不会进一步传播以绘制图纸。 Please note that when the listview is populated, the methods are called properly and the initial views are drawn. 请注意,在填充列表视图时,将正确调用方法并绘制初始视图。

I have spent substantial amount of time but somehow am missing the key ingredient. 我已经花费了大量时间,但是不知何故缺少了关键要素。 Could anyone please help? 谁能帮忙吗?

Thanks 谢谢

When the instance that is assigned to SetSheet is the same, then the DependencyPropertyChanged event won't trigger. 如果分配给SetSheet的实例相同,则不会触发DependencyPropertyChanged事件。 This would explain it all. 这将解释一切。 The point is the DependencyProperty checks old and new value for equality before setting the value. 关键是DependencyProperty在设置值之前检查新旧值是否相等。 If they are equal no change will be propagated. 如果它们相等,则不会传播任何更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM