2016-12-28 30 views
10

पर चयनित आइटम को दिखाने के लिए मैं कई वस्तुओं के साथ एक डेटा ग्रिड है और मैं प्रोग्राम के रूप में SelectedItem पर स्क्रॉल करने की जरूरत है। मैं StackOverflow और गूगल पर खोज की है, और ऐसा लगता समाधान ScrollIntoView है, इस प्रकार है:स्क्रॉल WPF डेटा ग्रिड शीर्ष

grid.ScrollIntoView(grid.SelectedItem) 

जो डेटा ग्रिड ऊपर या नीचे स्क्रॉल जब तक चयनित आइटम ध्यान में है। हालांकि, चयनित आइटम के लिए वर्तमान पुस्तक सापेक्ष स्थिति के आधार पर, चयनित आइटम अप डेटा ग्रिड के ScrollViewer में पिछले दिखाई आइटम जा रहा है हो सकता है। मैं चाहता हूँ कि चयनित आइटम ScrollViewer में पहला दृश्य आइटम (यह मानते हुए डेटा ग्रिड में पर्याप्त पंक्तियों इस अनुमति देने के लिए देखते हैं) हो जाएगा।

'FindVisualChild is a custom extension method that searches in the visual tree and returns 
'the first element of the specified type 
Dim sv = grid.FindVisualChild(Of ScrollViewer) 
If sv IsNot Nothing Then sv.ScrollToEnd() 
grid.ScrollIntoView(grid.SelectedItem) 

सबसे पहले मैं डेटा ग्रिड के अंत तक स्क्रॉल और उसके बाद ही मैं SelectedItem के लिए स्क्रॉल, जिस पर SelectedItem डेटा ग्रिड के शीर्ष पर दिखाया गया है इंगित करते हैं: तो मैं इस कोशिश की।

मेरे समस्या यह है कि डेटा ग्रिड के अंत तक स्क्रॉल करके अच्छी तरह से काम करता है, लेकिन बाद में चयनित आइटम पर स्क्रॉल करके हमेशा काम नहीं करता है।

मैं इस मुद्दे का समाधान कैसे कर सकते हैं, या वहाँ शीर्ष स्थान पर एक विशिष्ट रिकॉर्ड करने के लिए स्क्रॉल के लिए किसी अन्य वैकल्पिक रणनीति है?

उत्तर

3

this other question को स्वीकार कर लिया जवाब इस तरह के एक ग्रिड के प्रथम/अंतिम दिखाई पंक्ति प्राप्त करने के लिए एक अलग दृष्टिकोण को दर्शाता है। आप अपने पंक्ति के सूचकांक बाहर मिल सकता है और सीधे वहाँ स्क्रॉल करें या पहला दृश्य पंक्ति मैचों तक पंक्ति दर पंक्ति नीचे स्क्रॉल करें।

5

आप सही रास्ते पर थे, बस जरूरत है इस तरह का के लिए datagrid पर प्रत्यक्ष रूप से कार्य करने के बजाय संग्रह को देखने के साथ काम करने के लिए प्रयास करें।

यहाँ एक काम कर उदाहरण है जहाँ इच्छित आइटम हमेशा पहले चयनित आइटम के रूप में प्रदर्शित किया जाता है यदि संभव हो तो, अन्यथा ScrollViewer अंत करने के लिए स्क्रॉल किया जाता है और लक्ष्य मद में अपनी स्थिति पर चुना जाता है।

महत्वपूर्ण बिंदु हैं:

  • उपयोग CollectionView व्यापार पक्ष पर और "चयनित XAML नियंत्रण (IsSynchronizedWithCurrentItem=true)
  • आस्थगित करें आदेश अनुमति देने के लिए 'असली' लक्ष्य स्क्रॉल पर वर्तमान आइटम सिंक सक्षम अंतिम आइटम "visualy निष्पादित किया जाना है

यहाँ व्यापार तर्क (यह वीबी सी # से स्वत: रूपांतरण है)

है (एक कम प्राथमिकता के साथ एक Dispatcher.BeginInvoke का उपयोग करके)
Public Class Foo 

    Public Property FooNumber As Integer 
     Get 
     End Get 
     Set 
     End Set 
    End Property 
End Class 

Public Class MainWindow 
    Inherits Window 
    Implements INotifyPropertyChanged 

    Private _myCollectionView As ICollectionView 

    Public Sub New() 
     MyBase.New 
     DataContext = Me 
     InitializeComponent 
     MyCollection = New ObservableCollection(Of Foo) 
     MyCollectionView = CollectionViewSource.GetDefaultView(MyCollection) 
     Dim i As Integer = 0 
     Do While (i < 50) 
      MyCollection.Add(New Foo) 
      i = (i + 1) 
     Loop 

    End Sub 

    Public Property MyCollectionView As ICollectionView 
     Get 
      Return Me._myCollectionView 
     End Get 
     Set 
      Me._myCollectionView = value 
      Me.OnPropertyChanged("MyCollectionView") 
     End Set 
    End Property 

    Private Property MyCollection As ObservableCollection(Of Foo) 
     Get 
     End Get 
     Set 
     End Set 
    End Property 

    Private Sub ButtonBase_OnClick(ByVal sender As Object, ByVal e As RoutedEventArgs) 
     Dim targetNum As Integer = Convert.ToInt32(targetScroll.Text) 
     Dim targetObj As Foo = Me.MyCollection.FirstOrDefault(() => { }, (r.FooNumber = targetNum)) 

     'THIS IS WHERE THE MAGIC HAPPENS 
     If (Not (targetObj) Is Nothing) Then 
      'Move to the collection view to the last item 
      Me.MyCollectionView.MoveCurrentToLast 
      'Bring this last item into the view 
      Dim current = Me.MyCollectionView.CurrentItem 
      itemsContainer.ScrollIntoView(current) 
      'This is the trick : Invoking the real target item select with a low priority allows previous visual change (scroll to the last item) to be executed 
      Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, New Action(() => { }, Me.ScrollToTarget(targetObj))) 
     End If 

    End Sub 

    Private Sub ScrollToTarget(ByVal targetObj As Foo) 
     Me.MyCollectionView.MoveCurrentTo(targetObj) 
     itemsContainer.ScrollIntoView(targetObj) 
    End Sub 

    Public Event PropertyChanged As PropertyChangedEventHandler 

    Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String) 
     If (Not (PropertyChanged) Is Nothing) Then 
      PropertyChanged?.Invoke(Me, New PropertyChangedEventArgs(propertyName)) 
     End If 

    End Sub 
End Class 

और यह XAML

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition/> 
     <ColumnDefinition/> 
    </Grid.ColumnDefinitions> 
    <DataGrid x:Name="itemsContainer" ItemsSource="{Binding MyCollectionView}" IsSynchronizedWithCurrentItem="True" Margin="2" AutoGenerateColumns="False" > 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding FooNumber}"></DataGridTextColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

    <StackPanel Grid.Column="1"> 
     <TextBox x:Name="targetScroll" Text="2" Margin="2"></TextBox> 
     <Button Content="Scroll To item" Click="ButtonBase_OnClick" Margin="2"></Button> 
    </StackPanel> 
</Grid> 
3

मैं निम्नलिखित कोड के साथ इस सवाल का हल है:

public partial class MainWindow:Window 
{ 
    private ObservableCollection<Product> products=new ObservableCollection<Product>(); 

    public MainWindow() 
    { 
     InitializeComponent(); 

     for (int i = 0;i < 50;i++) 
     { 
      Product p=new Product { Name="Product "+i.ToString() }; 
      products.Add (p); 
     } 

     lstProduct.ItemsSource=products; 
    } 

    private void lstProduct_SelectionChanged(object sender,SelectionChangedEventArgs e) 
    { 
     products.Move (lstProduct.SelectedIndex,0); 
     lstProduct.ScrollIntoView (lstProduct.SelectedItem); 
    } 
} 

public class Product 
{ 
    public string Name { get; set; } 
} 


<Grid> 
    <ListBox Name="lstProduct" Margin="20" DisplayMemberPath="Name" SelectionChanged="lstProduct_SelectionChanged" /> 
</Grid> 
संबंधित मुद्दे