none
如何解决tabControl切换另一个tabItem,tabItem的内容在切回来ui上显示不一致的问题? RRS feed

  • 问题

  • 先上图

    如图所示每个tabitem内都有个ListView和一个textbox,我在第一个ListView先中几个,然后用鼠标操作一下滚动条进行滚动,然后切换第二个tabitem,在切换到第三个tabitem,然后在切回第一个tabitem,我发现原本在第一个tabitem的ListView里的选中的效果不见了,滚动条的所在位置跟在第三个tabitem中的listview的滚动条位置一样,或者显示在最上面的位置,总之切换tabitem时,ListView的滚动条的位置不可预见,切回来看到的是不会停留原来的位置,选中项也没有了

    总之切换TabItem,ListView的ui效果总会有怪现象,以及textbox也有,就是输入内容,在切到另一个tabitem在切回来,之前输入的内容不见了,变回原来的了,针对这些问题,我没有一点线索头绪,所以有大佬知道这是什么问题,如何解决?


    2018年10月4日 4:54

答案

  • Hi   轮回的齿轮,

    >>还是有滚动条的问题,我的设想是每个ListView的滚动条都是独立的,不会随着切换到下个tabitem而让下一个tabItem的ListView的滚动条的位置变得跟前一个ListView的滚动条位置一样,

    请根据下面的思路来实现:

    1: 点击每个Tab 时,获取当前滚动条的位置,并记录保存滚动条移动的位置。

    2: 切换到其他Tab和返回当前Tab的时候,将之前位置的值赋予滚动条。

    下面的代码供参考-简单实现恢复滚动条初始位置,请自己根据自己的代码进行调整,完善细节数据。

            private void tab_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                // ... Get TabControl reference.
                var item = sender as UIElement;
    
                foreach (ScrollViewer scv in FindVisualChildren<ScrollViewer>(item))
                {
                     //使用变量存储当前TabItem的滚动条的值。 然后再每次切换tab的时候重新定位。
                    scv.ScrollToVerticalOffset(0);
                }
            }
    
            public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
            {
                if (depObj != null)
                {
                    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                    {
                        DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                        if (child != null && child is T)
                        {
                            yield return (T)child;
                        }
    
                        foreach (T childOfChild in FindVisualChildren<T>(child))
                        {
                            yield return childOfChild;
                        }
                    }
                }
            }
    
    



    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月9日 6:56
    版主
  • HI   轮回的齿轮, 

    你的程序可以尝试将每个控件状态属性显式绑定到底层ViewModel上的专用属性来保留TabItem中的状态。这样,在切换TabItem的时候不会丢失。

    你可以参考下面代码。并逐步修改你的代码:

    DataModel:

     public class DataModel : INotifyPropertyChanged
        {
            public DataModel()
            {
                Title = Guid.NewGuid().ToString();
            }
            public string Title
            {
                set;
                get;
            }
    
            private bool isSelected =true;
    
            public bool IsSelected
            {
                get { return isSelected; }
                set
                {
                    isSelected = value;
                    
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }

    TabItemContent:

    public class TabItemContent : INotifyPropertyChanged
        {
            public TabItemContent(){
    
                List = new ObservableCollection<DataModel>();
                  }
            private ObservableCollection<DataModel> list;
            public ObservableCollection<DataModel> List
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("List"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
    
            private ObservableCollection<DataModel> selectlist;
            public ObservableCollection<DataModel> Selectlist
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Selectlist"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }

    TabControl:

     <TabControl  Style="{StaticResource TabControlStyle}" ItemContainerStyle="{StaticResource MyTab}" Name="tab" HorizontalAlignment="Left" Height="329" Margin="50,25,0,0" VerticalAlignment="Top" Width="868"  RenderTransformOrigin="0.5,0.5">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <DockPanel  >
                            <TextBlock DockPanel.Dock="Left" FontSize="20" Text="{Binding Tittle,Mode=TwoWay}" />
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <TextBox FontSize="20" Margin="4" Text="{Binding Id ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Top" Tag="date" >
                            </TextBox>
                            <Border BorderBrush="Gray" DockPanel.Dock="Bottom" BorderThickness="1" Margin="4"  >
                                <ListView   ItemsSource="{Binding Path=ItemContent.List}"   SelectedItem="{Binding ItemContent.Selectlist, Mode=TwoWay}"  >
                                    <ListView.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding Path=Title}"></TextBlock>
                                        </DataTemplate>
                                    </ListView.ItemTemplate>
                                    <ListView.ItemContainerStyle>
                                        <Style TargetType="{x:Type ListViewItem}">
                                            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
                                        </Style>
                                    </ListView.ItemContainerStyle>
                                </ListView>
                            </Border>
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ContentTemplate>
            </TabControl>

    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    还是有滚动条的问题,我的设想是每个ListView的滚动条都是独立的,不会随着切换到下个tabitem而让下一个tabItem的ListView的滚动条的位置变得跟前一个ListView的滚动条位置一样,

    2018年10月9日 5:20

全部回复

  • Hi  轮回的齿轮,

    >>总之切换tabitem时,ListView的滚动条的位置不可预见,切回来看到的是不会停留原来的位置,选中项也没有了

    我尝试做了一个小Demo,并没有发现你所述的现象。也许你的程序中有其他的设置或者代码导致了此问题。也许你可以上传一个可还原的Demo给我们测试下。

    Best Regards,

    Yong Lu

     

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月5日 5:49
    版主
  • Hi  轮回的齿轮,

    >>总之切换tabitem时,ListView的滚动条的位置不可预见,切回来看到的是不会停留原来的位置,选中项也没有了

    我尝试做了一个小Demo,并没有发现你所述的现象。也许你的程序中有其他的设置或者代码导致了此问题。也许你可以上传一个可还原的Demo给我们测试下。

    Best Regards,

    Yong Lu

     

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    <TabControl  Name="tab" HorizontalAlignment="Left" Height="329" Margin="50,25,0,0" VerticalAlignment="Top" Width="868" RenderTransformOrigin="0.5,0.5">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <DockPanel  >
                            <TextBlock DockPanel.Dock="Left" FontSize="20" Text="{Binding Tittle,Mode=TwoWay}" />
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <TextBox FontSize="20" Margin="4" Text="{Binding Id}" DockPanel.Dock="Top" >
                            </TextBox>
                            <Border BorderBrush="Gray" BorderThickness="1" Margin="4"  >
                                <ListView   ItemsSource="{Binding Path=ItemContent.List}" >
                                    <ListView.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding Path=Title}"></TextBlock>
                                        </DataTemplate>
                                    </ListView.ItemTemplate>
                                </ListView>
                            </Border>
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ContentTemplate>
            </TabControl>

    这是简化的xaml,把tabControl的style和ItemContainerStyle都去掉了,不过还是有我提问里的描述的问题情况。tabControl的绑定是在后台的通过Window_Loaded用ItemsSource属性进行绑定的。

    public class TabModel : INotifyPropertyChanged
        {
    
            private static int RowId=0;
            public TabModel(string tittle,bool isSelected)
            {
                this.Id = ++RowId;
                this.Tittle = tittle;
                this.IsSelected = isSelected;
                ItemContent = new TabItemContent();
            }
            public int Id
            {
                set;
                get;
            }
    
            private string tittle;
            public string Tittle
            {
                set
                {
                    tittle = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Tittle"));
                    }
                }
                get
                {
                    return tittle;
                }
            }
    
            private bool isSelected; 
            public bool IsSelected
            {
                set
                {
                    isSelected = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("IsSelected")); 
                    }
                }
                get
                {
                    return isSelected;
                }
            }
    
            private TabItemContent itemContent ;
            public TabItemContent ItemContent 
            {
                set
                {
                    itemContent = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("ItemContent "));  
                    }
                }
                get
                {
                    return itemContent ;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }

    2018年10月6日 5:30

  • Hi   轮回的齿轮,

    我尝试了你的代码,但是不能还原你的问题,请补全你的代码以便能重现问题或者直接上传一个可运行的demo。以便快速准确的分析问题。

    Best Regards,

    Yong Lu

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2018年10月8日 2:42
    版主

  • Hi   轮回的齿轮,

    我尝试了你的代码,但是不能还原你的问题,请补全你的代码以便能重现问题或者直接上传一个可运行的demo。以便快速准确的分析问题。

    Best Regards,

    Yong Lu

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    https://pan.baidu.com/s/1mzVrGJctn3svnq1gsVo6Ng 简化项目下载地址
    2018年10月8日 5:33
  • HI   轮回的齿轮, 

    你的程序可以尝试将每个控件状态属性显式绑定到底层ViewModel上的专用属性来保留TabItem中的状态。这样,在切换TabItem的时候不会丢失。

    你可以参考下面代码。并逐步修改你的代码:

    DataModel:

     public class DataModel : INotifyPropertyChanged
        {
            public DataModel()
            {
                Title = Guid.NewGuid().ToString();
            }
            public string Title
            {
                set;
                get;
            }
    
            private bool isSelected =true;
    
            public bool IsSelected
            {
                get { return isSelected; }
                set
                {
                    isSelected = value;
                    
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }

    TabItemContent:

    public class TabItemContent : INotifyPropertyChanged
        {
            public TabItemContent(){
    
                List = new ObservableCollection<DataModel>();
                  }
            private ObservableCollection<DataModel> list;
            public ObservableCollection<DataModel> List
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("List"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
    
            private ObservableCollection<DataModel> selectlist;
            public ObservableCollection<DataModel> Selectlist
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Selectlist"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    

    TabControl:

     <TabControl  Style="{StaticResource TabControlStyle}" ItemContainerStyle="{StaticResource MyTab}" Name="tab" HorizontalAlignment="Left" Height="329" Margin="50,25,0,0" VerticalAlignment="Top" Width="868"  RenderTransformOrigin="0.5,0.5">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <DockPanel  >
                            <TextBlock DockPanel.Dock="Left" FontSize="20" Text="{Binding Tittle,Mode=TwoWay}" />
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <TextBox FontSize="20" Margin="4" Text="{Binding Id ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Top" Tag="date" >
                            </TextBox>
                            <Border BorderBrush="Gray" DockPanel.Dock="Bottom" BorderThickness="1" Margin="4"  >
                                <ListView   ItemsSource="{Binding Path=ItemContent.List}"   SelectedItem="{Binding ItemContent.Selectlist, Mode=TwoWay}"  >
                                    <ListView.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding Path=Title}"></TextBlock>
                                        </DataTemplate>
                                    </ListView.ItemTemplate>
                                    <ListView.ItemContainerStyle>
                                        <Style TargetType="{x:Type ListViewItem}">
                                            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
                                        </Style>
                                    </ListView.ItemContainerStyle>
                                </ListView>
                            </Border>
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ContentTemplate>
            </TabControl>
    

    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月8日 9:01
    版主
  • HI   轮回的齿轮, 

    你的程序可以尝试将每个控件状态属性显式绑定到底层ViewModel上的专用属性来保留TabItem中的状态。这样,在切换TabItem的时候不会丢失。

    你可以参考下面代码。并逐步修改你的代码:

    DataModel:

     public class DataModel : INotifyPropertyChanged
        {
            public DataModel()
            {
                Title = Guid.NewGuid().ToString();
            }
            public string Title
            {
                set;
                get;
            }
    
            private bool isSelected =true;
    
            public bool IsSelected
            {
                get { return isSelected; }
                set
                {
                    isSelected = value;
                    
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }

    TabItemContent:

    public class TabItemContent : INotifyPropertyChanged
        {
            public TabItemContent(){
    
                List = new ObservableCollection<DataModel>();
                  }
            private ObservableCollection<DataModel> list;
            public ObservableCollection<DataModel> List
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("List"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
    
            private ObservableCollection<DataModel> selectlist;
            public ObservableCollection<DataModel> Selectlist
            {
                set
                {
                    list = value;
                    if (PropertyChanged != null)//有改变  
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Selectlist"));
                    }
                }
                get
                {
                    return list;
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }

    TabControl:

     <TabControl  Style="{StaticResource TabControlStyle}" ItemContainerStyle="{StaticResource MyTab}" Name="tab" HorizontalAlignment="Left" Height="329" Margin="50,25,0,0" VerticalAlignment="Top" Width="868"  RenderTransformOrigin="0.5,0.5">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <DockPanel  >
                            <TextBlock DockPanel.Dock="Left" FontSize="20" Text="{Binding Tittle,Mode=TwoWay}" />
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <TextBox FontSize="20" Margin="4" Text="{Binding Id ,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Top" Tag="date" >
                            </TextBox>
                            <Border BorderBrush="Gray" DockPanel.Dock="Bottom" BorderThickness="1" Margin="4"  >
                                <ListView   ItemsSource="{Binding Path=ItemContent.List}"   SelectedItem="{Binding ItemContent.Selectlist, Mode=TwoWay}"  >
                                    <ListView.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding Path=Title}"></TextBlock>
                                        </DataTemplate>
                                    </ListView.ItemTemplate>
                                    <ListView.ItemContainerStyle>
                                        <Style TargetType="{x:Type ListViewItem}">
                                            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
                                        </Style>
                                    </ListView.ItemContainerStyle>
                                </ListView>
                            </Border>
                        </DockPanel>
                    </DataTemplate>
                </TabControl.ContentTemplate>
            </TabControl>

    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    还是有滚动条的问题,我的设想是每个ListView的滚动条都是独立的,不会随着切换到下个tabitem而让下一个tabItem的ListView的滚动条的位置变得跟前一个ListView的滚动条位置一样,

    2018年10月9日 5:20
  • Hi   轮回的齿轮,

    >>还是有滚动条的问题,我的设想是每个ListView的滚动条都是独立的,不会随着切换到下个tabitem而让下一个tabItem的ListView的滚动条的位置变得跟前一个ListView的滚动条位置一样,

    请根据下面的思路来实现:

    1: 点击每个Tab 时,获取当前滚动条的位置,并记录保存滚动条移动的位置。

    2: 切换到其他Tab和返回当前Tab的时候,将之前位置的值赋予滚动条。

    下面的代码供参考-简单实现恢复滚动条初始位置,请自己根据自己的代码进行调整,完善细节数据。

            private void tab_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                // ... Get TabControl reference.
                var item = sender as UIElement;
    
                foreach (ScrollViewer scv in FindVisualChildren<ScrollViewer>(item))
                {
                     //使用变量存储当前TabItem的滚动条的值。 然后再每次切换tab的时候重新定位。
                    scv.ScrollToVerticalOffset(0);
                }
            }
    
            public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
            {
                if (depObj != null)
                {
                    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                    {
                        DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                        if (child != null && child is T)
                        {
                            yield return (T)child;
                        }
    
                        foreach (T childOfChild in FindVisualChildren<T>(child))
                        {
                            yield return childOfChild;
                        }
                    }
                }
            }
    
    



    Best Regards,

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年10月9日 6:56
    版主