Question

I have a ObservableCollection with many items. Each item has properties called Text and Anzahl. These 2 properties should be displayed in 2 different textblocks. I have already achieved that. In my AppBar, I have two Buttons. One to display the next item and one to step one back.

Can I achieve that with bindings? What is the easiest way?

Was it helpful?

Solution

First of all bind your "Next" and "Previous" Button to Command and in the Command Action, set properties "Foo" and "Bar" (which are properties binded to your respective textblocks) with respect to current element.

for iterating through your ObservableCollection maintain one index variable at class scope like

int iterator=0;

and in your actions(previous and next) do like this

public void NextAction()
{
    iterator++;
    Foo=MainList[iterator].Text;
    Bar=MainList[iterator].Anzal;
}

public void PreviousAction()
{
    iterator--;
    Foo=MainList[iterator].Text;
    Bar=MainList[iterator].Anzal;
}

And don't forget to implement RaisePropertyChange to your Foo and Bar properties' set method..

OTHER TIPS

As others have mentioned, it's hard to help precisely when we don't have context. Distilling your problem to a minimal code representation would be extremely helpful. For example, Rushi Soni's answer will work if your controls are bound to individual properties on a class, but there is another answer if you've bound your TextBlocks directly to your ObservableCollection:

By default, non-list controls like TextBlock which are bound to a collection will display the "current" item in the list. WPF maintains a (somewhat magical) view of the collection that keeps track of the current item. You can access the collection view by calling CollectionViewSource.GetDefaultView(ObservableCollection) and manipulate the current item by using methods MoveCurrentToPrevious, MoveCurrentToNext, IsCurrentBeforeFirst, and IsCurrentAfterLast on the returned ICollectionView interface.

Full code for this scenario:

XAML:

<UserControl.Resources>
    <!-- the MyCollection type is derived from ObservableCollection<MyItem> -->
    <my:MyCollection x:Key="myCollection">
        <my:MyItem Text="One" Anzhal="1"/>
        <my:MyItem Text="Two" Anzhal="2"/>
        <my:MyItem Text="Three" Anzhal="3"/>
    </my:MyCollection>
</UserControl.Resources>

<!-- data context of the top level control is the observable collection defined here in XAML, but
could also be created and assigned in code -->
<DockPanel Name="grid1" DataContext="{StaticResource myCollection}"  >
    <!-- navigation controls -->
    <Grid DockPanel.Dock="Top" >
        <Button HorizontalAlignment="Left" Content="&lt; Previous" Name="buttonPrev" Click="buttonPrev_Click" />
        <Button HorizontalAlignment="Right" Content="Next &gt;" Name="buttonNext" Click="buttonNext_Click" />
    </Grid>

    <!-- display of the current item -->
    <TextBlock Padding="5" DockPanel.Dock="Top" Text="{Binding Text}" />
    <TextBlock Padding="5" DockPanel.Dock="Top" Text="{Binding Anzhal}" />

    <!-- list display of all items (not necessary but helpful for visualizing the behavior) -->
    <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Text" />
</DockPanel>

Class definitions for the collection and the contained items:

public class MyCollection : ObservableCollection<MyItem> { }

public class MyItem
{
    // NOTE: these must be get/set properties in order for binding to work
    public string Text { get; set; }
    public int Anzhal { get; set; }
}

And the code for handling the Next/Previous button clicks, which demonstrates wrapping around when reaching the ends of the collection:

ICollectionView GetView()
{
    // use FindResource() to retrieve the collection since it is defined in XAML
    // Then we retrieve WPF's view into the collection so we can manipulate the 
    // current item (next, previous)

    return CollectionViewSource.GetDefaultView(FindResource("myCollection"));
}

private void buttonNext_Click(object sender, RoutedEventArgs e)
{
    var view = GetView();

    // wrap around behavior
    view.MoveCurrentToNext();
    if (view.IsCurrentAfterLast) {
        view.MoveCurrentToFirst();
    }
}

private void buttonPrev_Click(object sender, RoutedEventArgs e)
{
    var view = GetView();

    // wrap around behavior
    view.MoveCurrentToPrevious();
    if (view.IsCurrentBeforeFirst) {
        view.MoveCurrentToLast();
    }
}

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top