Dropping item between listviews animation - c#

I have 2 ListView controls bound to 2 different ObservableCollection<string> like this:
<ListView x:Name="List1"
Grid.Column="0"
CanDragItems="True"
CanReorderItems="True"
AllowDrop="True"/>
<ListView x:Name="List2"
Grid.Column="1"
CanDragItems="True"
CanReorderItems="True"
AllowDrop="True"/>
When dragging and dropping items in their own respective lists I get the default animation like this:
But I cannot get the same animation when I hover over the second ListView. Why is that and how can I invoke the same animation in this case? I can handle what happens on drop but first I need to be able to invoke the same animation.
All current solution I have gone through does not have the animation or uses some other library/control to substitute for this. Any help or suggestion regarding this is appreciated.

There is no default drop animation for a ListView. You'll need to create something yourself - or use a third party solution such as you report to have already found.

Related

Unable to Programmatically Navigate Dynamic ListView

<ListView x:Name="myListView" ItemsSource="{x:Bind PageViewModel.myCollectionOfThings, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:ThingViewModel>
<TextBlock Text="{x:Bind Name, Mode=OneWay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Name="TestButton" Tapped="TestButton_Tapped"/>
private void TestButton_Tapped(object sender, TappedRoutedEventArgs e)
{
PageViewModel.myCollectionOfThings.Add(newItem);
myListView.SelectedIndex++;
}
I'm trying to create a carousel control**. Using the code above I can dynamically add an item to the end of the collection each time its selected index increases. It works as one would expect except one problem. Even though the UI is reflecting the new items added to the end of the ListView, if I iterate past the last index of the original collection size, the UI jumps back to the beginning of the list and the selected index becomes 0. I've tried many variations of the above code and tried different collection types. I've also tried re-assigning the ListView's ItemSource each iteration which didn't do anything. Any help would be appreciated.
**I know there's something called Carousel in the UWP Community Toolkit but it isn't actually a carousel. A carousel can scroll endlessly as its collection will loop, which that control does not do.
If you want Carousel that can scroll endlessly then take a look at the Carousel control in the Windows AppStudio NuGet package. Download Windows App Studio UWP Samples to learn about the control.
Here an image of this Carousel Control
It looks like the listview is rebinding with binding source when the collection is changed. Try to re-set the index manually after adding the item.
int currentIndex = myListView.SelectedIndex;
PageViewModel.myCollectionOfThings.Add(newItem);
myListView.SelectedIndex = currentIndex++;
// If above doesn't work try setting selectedItem property to newItem.

How to get rid of double selection thing in ListView (XAML)

I have a ListView and I bind to an ObservableCollection<Folder> and when I hover over a ListViewItem, there is a second selection thing appearing underneath (or ontop of) the item text which prevents me from being able to "activate" the selected item because it doesn't appear to be receiving my click.
As you can probably see, the structure is:
ListView > ItemTemplate > DataTemplate > ListViewItem. But I'm guessing I have that double-selection thing because there are basically 2 "item templates" (DataTemplate and ItemTemplate). But if I get rid of DataTemplate, it throws a runtime error. If I get rid of ItemTemplate, it throws an error. I can't win. How do I get rid of this thing?
Update:
This gives me the desired effect:
<StackPanel x:Name="folderContainer" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="175" Background="Khaki" Margin="0, 18, 0, 0">
<ListView x:Name="folderList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Folder}" BorderBrush="{x:Null}" BorderThickness="0">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="folderItem" Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
With the ListViewItem you where including a specialized wrapper primarily used the ListView to contain unknown item(s) presented by the binding of the ItemsSource when there is default template used. It helps to show that unknown item on the screen, its the purpose of the ListViewItem. For example if someone bound a list of strings, the strings have no xaml style on hover, hence there needs to be a container control to achieve all things graphical in those situations.
Why the two Shadows?
The actual ListViewItem is at its heart (or actually its property), a content control containing what I surmise you had was a textbox control. That is now two controls thanks to the DataTemplate you provided.
Hence you had a wrapper, with a content containing a texbox control. So there are two things which take up space, one is the ListViewItem and the other is the textbox. By hovering over each item, each's style kicked off to show the padding of the control as a selectable region in the Zorder fashion whereas both are seen.
Nothing more nothing less.
Since you knew what is to go into the content control, there was no need to use the ListViewItem wrapper, it was redundant, and you used the actual textbox; hence with only it's style to show the padding of the single control on hover.

WPF: Which solution? TabControl with close button and new tab button

I'm trying to find the best solution for a TabControl that both support a close button on each TabItem, and always show a "new tab button" as the last tab.
I've found some half working solutions, but i think that was for MVVM, that I'm not using. Enough to try to understand WPF =)
This is the best solution I've found so far:
http://www.codeproject.com/Articles/493538/Add-Remove-Tabs-Dynamically-in-WPF
A solution that i actually understand. But the problem is that it is using the ItemsSource, and i don't want that. I want to bind the ItemsSource to my own collection without having to have special things in that collection to handle the new tab button.
I've been search for days now but cant find a good solution.
And I'm really new to WPF, otherwise i could probably have adapted the half done solutions I've found, or make them complete. But unfortunately that is way out of my league for now.
Any help appreciated.
I have an open source library which supports MVVM and allows extra content, such as a button to be added into the tab strip. It is sports Chrome style tabs which can tear off.
http://dragablz.net
This is bit of a dirty way to achieve the Add (+) button placed next to the last TabItem without much work. You already know how to place a Delete button next to the TabItem caption so I've not included that logic here.
Basically the logic in this solution is
To bind ItemsSource property to your own collection as well as
the Add TabItem using a CompositeCollection.
Disable selection of
the Add(+) TabItem and instead perform an action to load a new tab when it
is clicked/selected.
XAML bit
<TextBlock x:Name="HiddenItemWithDataContext" Visibility="Collapsed" />
<TabControl x:Name="Tab1" SelectionChanged="Tab1_SelectionChanged" >
<TabControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding DataContext.MyList, Source={x:Reference HiddenItemWithDataContext}}" />
<TabItem Height="0" Width="0" />
<TabItem Header="+" x:Name="AddTabButton"/>
</CompositeCollection>
</TabControl.ItemsSource>
</TabControl>
The code behind
private void Tab1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Contains(AddTabButton))
{
//Logic for adding a new item to the bound collection goes here.
string newItem = "Item " + (MyList.Count + 1);
MyList.Add(newItem);
e.Handled = true;
Dispatcher.BeginInvoke(new Action(() => Tab1.SelectedItem = newItem));
}
}
You could make a converter which appends the Add tab. This way the collection of tabs in you viewmodel will only contain the real tabs.
The problem is then how to know when the Add tab is selected. You could make a TabItem behavior which executes a command when the tab is selected. Incidentally I recommended this for another question just recently, so you can take the code from there: TabItem selected behavior
While I don't actually have the coded solution, I can give some insight on what is most likely the appropriate way to handle this in a WPF/MVVM pattern.
Firstly, if we break down the request it is as follows:
You have a sequence of elements that you want to display.
You want the user to be able to remove an individual element from the sequence.
You want the user to be able to add a new element to the sequence.
Additionally, since you are attempting to use a TabControl, you are also looking to get the behavior that a Selector control provides (element selection), as well as an area to display the element (content) which is selected.
So, if we stick to these behaviors you'll be fine, since the user interface controls can be customized in terms of look and feel.
Of course, the best control for this is the TabControl, which are you already trying to use. If we use this control, it satisfies the first item.
<TabControl ItemsSource="{Binding Path=Customers}" />
Afterwards, you can customize each element, in your case you want to add a Button to each element which will execute a command to remove that element from the sequence. This will satisfy the second item.
<TabControl ...>
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=CustomerId}" />
<Button Command="{Binding Path=RemoveItemCommand, Mode=OneTime,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TabControl}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
<TabControl.ItemTemplate>
</TabControl>
The last part is a bit more difficult, and will require you to actually have to create a custom control that inherits from the TabControl class, add an ICommand DependencyProperty, and customize the control template so that it not only displays the TabPanel, but right next to it also displays a Button which handles the DependencyProperty you just created (the look and feel of the button will have to be customized as well). Doing all of this will allow you to display your own version of a TabControl which has a faux TabItem, which of course is your "Add" button. This is far far far easier said than done, and I wish you luck. Just remember that the TabPanel wraps onto multiple rows and can go both horizontally or vertically. Basically, this last part is not easy at all.

ListView : how to always scroll to the bottom

I have a list view that I want to scroll to the bottom as I add items into the "Items" list.
As I add items they appear in the ListView, but when I reach the limit of the screen, the list remains showing the top section and new items are added to the bottom. If I scroll down I can see the new items. I'd like it to auto scroll to the bottom so that I can always see the latest items in the list.
<ListView
x:Name="lvBasketContent"
Grid.Row="1"
ItemsSource="{Binding Items}"
ItemContainerStyle="{StaticResource ListViewItemStyle1}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Bottom"
SelectionMode="None"
IsSwipeEnabled="False"
VerticalAlignment="Top"
>
Can anyone help me out please?
You need to create a custom behavior or derived implementation of ListView.
This class should monitor the ItemsSource collection for changes and call ListViewBase.ScrollIntoView(Object), passing in the item that you want to show. In your case, this may be the last one added.
I recommended the behavior as it keeps your code modular as you can use it on any listview in your solution by changing the xaml only.
I'm not going to write the code for you as behaviors are a very useful technique to learn first hand. The first link should give you all you need to get cracking.
Do you can try put this in your code ? Each time you add an item to your listbox , try call it
//Add an item in the listbox
lvBasketContent.Items.Add(...);
//...
//Scroll to bottom
lvBasketContent.SelectedIndex = lvBasketContent.Items.Count -1
lvBasketContent.ScrollIntoView(lvBasketContent.SelectedItem)

WPF Combobox issue

I have a combo box in a wpf c# application. In the xaml i am trying to do the following.
The ItemsSource comes from one variable.
SelectedItem sets a value on another variable
But i want the text displayed to come from a new variable.
How do i stop making the selected itemssource appear as the main text?
<ComboBox x:Name="ComboPlay" FontSize="14" MinHeight="20" Margin="0,2,4,4" Grid.Row="1" Grid.Column="3" MinWidth="160"
ItemsSource="{Binding ComboBoxList}"
SelectedItem="{Binding OutputChannel.Value, Converter={StaticResource ResourceKey=ValueToStringConverter}}" Grid.ColumnSpan="1"
IsEnabled="{Binding IsDriveChoiceEnabled}"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
If you mean changing the display of the item currently selected (the portion of the control shown when the dropdown is closed), take a look at Can I use a different Template for the selected item in a WPF ComboBox than for the items in the dropdown part?
Honestly, a quick search dug up that one and many similar ones. Probably the simplest way, like the linked answer, is to figure out if your item is wrapped in a ComboBoxItem and display it differently then. Or you could re-template the ComboBox. Or you could derive from it (and re-template it) and provide a separate dependency property for the template of the selected item, if you expect to reuse it in different contexts. The sky's the limit.

Categories

Resources