I am proto-typing a (Windows 10 universal app) UI and have built a very simple/rough user control to act as a 'badge', i.e show a numeric value in a circle, and animate the value changing. My issue is the control works if there is only a single instance of it in an application page. If there are multiple instances (even if the other instances are invisible), then only the last declared instance animates.
I've tried declaring the animation both in the user control's XAML, and in code behind to attempt to ensure there's no cross-over/mix up with the animation being shared. I also added a change callback to the property being animated, which writes the property value out using Debug.WriteLine. For control instances that animate properly the value changes as expected, i.e if we go from 10 to 20, the property is set to 10, 11, 12, 13.... 20. For the instances that don't work, the value is just set to the from property every time, i.e 10, 10, 10, 10, 10.
Below is a sample of the user control, and then a sample page that uses three instances of it. Placing both of these is a new Windows 10 Universal app called App3 should reproduce the issue. In the sample page the first two badges don't animate properly when their button is clicked, but the last one does.
Is anyone able to point out what I'm doing wrong, and why this breaks with multiple instances on a page?
Thanks.
Note: The code has gotten quite rough as I've hacked things around trying to figure out what the issue is, and it was only prototype code to begin with, so I apologize for the mess.
<UserControl
x:Class="App3.BadgeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="20">
<Grid>
<Ellipse x:Name="Border" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{Binding BadgeBorderBrush}" />
<Ellipse x:Name="BadgeInner" Margin="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{Binding BadgeFillBrush}" />
<TextBlock x:Name="BadgeValue" Margin="5" HorizontalAlignment="Center" FontSize="10" VerticalAlignment="Center" TextAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="White" Text="{Binding DisplayValue}" />
</Grid>
public sealed partial class BadgeView : UserControl
{
public DependencyProperty BadgeBorderBrushProperty = DependencyProperty.Register("BadgeBorderBrush", typeof(Brush), typeof(BadgeView), new PropertyMetadata(new SolidColorBrush(Windows.UI.Colors.Yellow)));
public DependencyProperty BadgeFillBrushProperty = DependencyProperty.Register("BadgeFillBrush", typeof(Brush), typeof(BadgeView), new PropertyMetadata(new SolidColorBrush(Windows.UI.Colors.Orange)));
public DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(BadgeView), new PropertyMetadata(0, new PropertyChangedCallback(ValueChanged)));
public DependencyProperty DisplayValueProperty = DependencyProperty.Register("DisplayValue", typeof(int), typeof(BadgeView), new PropertyMetadata(0, DisplayValueChanged));
private static void DisplayValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(((BadgeView)d).DisplayValue);
}
private Storyboard AnimateBadgeValueCount;
private DoubleAnimation BadgeValueAnimation;
public BadgeView()
{
this.InitializeComponent();
this.BadgeValue.DataContext = this.BadgeInner.DataContext = this.Border.DataContext = this;
AnimateBadgeValueCount = new Storyboard(); ;
AnimateBadgeValueCount.Duration = TimeSpan.FromSeconds(0.5);
Storyboard.AllowDependentAnimations = true;
BadgeValueAnimation = new DoubleAnimation();
BadgeValueAnimation.Duration = TimeSpan.FromSeconds(0.5);
BadgeValueAnimation.EnableDependentAnimation = true;
BadgeValueAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
this.AnimateBadgeValueCount.FillBehavior = FillBehavior.Stop;
this.BadgeValueAnimation.FillBehavior = FillBehavior.Stop;
AnimateBadgeValueCount.Children.Add(BadgeValueAnimation);
Storyboard.SetTarget(AnimateBadgeValueCount, this);
Storyboard.SetTargetProperty(AnimateBadgeValueCount, "DisplayValue");
this.AnimateBadgeValueCount.Completed += AnimateBadgeValueCount_Completed;
}
private void AnimateBadgeValueCount_Completed(object sender, object e)
{
this.DisplayValue = this.Value;
}
private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var badgeView = (BadgeView)d;
badgeView.AnimateValue();
}
private void AnimateValue()
{
if (Value != DisplayValue)
{
this.BadgeValue.DataContext = this.BadgeInner.DataContext = this.Border.DataContext = this;
this.AnimateBadgeValueCount.Stop();
this.BadgeValueAnimation.From = this.DisplayValue;
this.BadgeValueAnimation.To = this.Value;
this.BadgeValueAnimation.FillBehavior = FillBehavior.Stop;
//Storyboard.SetTarget(this.AnimateBadgeValueCount, this);
//Storyboard.SetTargetProperty(this.AnimateBadgeValueCount, "DisplayValue");
this.AnimateBadgeValueCount.Begin();
}
}
public Brush BadgeBorderBrush
{
get { return (Brush)this.GetValue(this.BadgeBorderBrushProperty); }
set
{
this.SetValue(this.BadgeBorderBrushProperty, value);
}
}
public Brush BadgeFillBrush
{
get { return (Brush)this.GetValue(this.BadgeFillBrushProperty); }
set
{
this.SetValue(this.BadgeFillBrushProperty, value);
}
}
public int Value
{
get { return (int)this.GetValue(ValueProperty); }
set
{
this.SetValue(ValueProperty, value);
}
}
public int DisplayValue
{
get { return (int)this.GetValue(DisplayValueProperty); }
set
{
this.SetValue(DisplayValueProperty, value);
}
}
}
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Orientation="Vertical">
<Button Content="Do it" x:Name="DoIt1" Click="DoIt1_Click" />
<local:BadgeView x:Name="Badge1" Width="20" Height="20" BadgeFillBrush="Blue" />
<Button Content="Do it" x:Name="DoIt2" Click="DoIt2_Click" />
<local:BadgeView x:Name="Badge2" Width="20" Height="20" />
<Button Content="Do it" x:Name="DoIt3" Click="DoIt3_Click" />
<local:BadgeView x:Name="Badge3" Width="20" Height="20" />
</StackPanel>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void DoIt1_Click(object sender, RoutedEventArgs e)
{
this.Badge1.Value += 10;
}
private void DoIt2_Click(object sender, RoutedEventArgs e)
{
this.Badge2.Value += 10;
}
private void DoIt3_Click(object sender, RoutedEventArgs e)
{
this.Badge3.Value += 10;
}
}
What I have done is simplify code and simplify and move the datacontext inside the loaded event inside the constructor:
this.Loaded += (s, e) =>
{
this.DataContext = this;
AnimateBadgeValueCount = new Storyboard(); ;
AnimateBadgeValueCount.Duration = TimeSpan.FromSeconds(0.5);
BadgeValueAnimation = new DoubleAnimation();
BadgeValueAnimation.Duration = TimeSpan.FromSeconds(0.5);
//BadgeValueAnimation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
AnimateBadgeValueCount.Children.Add(BadgeValueAnimation);
Storyboard.SetTarget(AnimateBadgeValueCount, this);
Storyboard.SetTargetProperty(AnimateBadgeValueCount, "DisplayValue");
this.AnimateBadgeValueCount.Completed += AnimateBadgeValueCount_Completed;
};
private async void AnimateValue()
{
if (Value != DisplayValue)
{
this.AnimateBadgeValueCount.Stop();
this.BadgeValueAnimation.From = this.DisplayValue;
this.BadgeValueAnimation.To = this.Value;
BadgeValueAnimation.EnableDependentAnimation = true;
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
{
this.AnimateBadgeValueCount.Begin();
});
}
}
I have commented the EasingFunction, it works but in my opinion fit betters.
It is curious, because if I set the datacontext just in the constructor it works bad, but inside goes fine.
Tell me if you try.
Related
I have this strange problem, where the binding seems completely ignored.
my xaml
<Button IsEnabled="{Binding ButtonEnabled}" x:Name="ButtonOK" BackgroundColor="Green" TextColor="White" Text="OK"/>
my C#
private bool _buttonEnabled = false;
public bool ButtonEnabled
{
get
{
// breakpoint 1, which never hits with value = false
return _buttonEnabled;
}
set
{
// breakpoint 2, which hits
_buttonEnabled = value;
OnPropertyChanged(nameof(ButtonEnabled));
}
}
private void ChassisEntry_TextChanged(object sender, TextChangedEventArgs e)
{
ButtonEnabled = ChassisEntry.Text != "";
}
private void PageScan_Appearing(object sender, EventArgs e)
{
ChassisEntry.Text = "";
}
I expect that when this page opens that ButtonOK is disabled, but it is not.
When I set breakpoints then breakpoint 1 (in the getter) never hits, its like if the xaml IsEnabled="{Binding ButtonEnabled}" is ignored.
The breakpoint 2 does hits, with value = false
What am I missing here ?
I googled this problem and found many similar questions, but all solutions given do not help with my problem.
Button IsEnabled binding not working properly
How to disable a button until all entries are filled?
Disable/Enable save button based on the mandatory field being null or empty using Behaviors
and many more
I am guessing you are using the xaml.cs page for holding your Bindings and hence if you are doing that there are two ways to do this
Set the BindingContext to the current class in the constructor before or right after InitializeComponent
BindingContext= this;
Or In your XAML
<ContentPage
....
x:Name="currentPage">
And in your button
<Button IsEnabled="{Binding ButtonEnabled, Source={x:Reference currentPage}}"
I would go with this: Set my Button in my XAML disabled.
<Button IsEnabled="False" x:Name="ButtonOK" BackgroundColor="Green" TextColor="White" Text="OK"/>
Then on my Entry control i would add the property TextChanged.
<Entry x:Name="ChassisEntry"
PlaceholderColor="DarkGray"
TextChanged="ChassisEntryChanged">
On xaml.cs file:
private void ChassisEntryChanged(object sender, TextChangedEventArgs e)
{
if (e.NewTextValue.Text != "")
{
ButtonOK.IsEnabled = true;
}
else
{
ButtonOK.IsEnabled = false;
}
}
I have created a custom control that has horizontal bar there can be N number of boxview in the bar based on number I get from API for example i have a control with limit of 20 controls and i have selected 10 of them so 10 boxview will be on orange and remaining 10 from 20 will be black
i need to update control on every checkbox selection and it is working fine for me till i go to next screen and come back to the same screen once i come back to this screen control stops updating wile debug i get data in my code but its not updating on UI.
How i use it in my code
<views:CustomDashControl
x:Name="customDash"
Grid.Row="2"
Grid.ColumnSpan="3"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding ControlData}"
VerticalOptions="Start" />
My CustomControl XAML
<ContentView
x:Class="LIRAppV1.Controls.CustomDashControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<StackLayout
Padding="1"
BackgroundColor="White"
HorizontalOptions="CenterAndExpand"
VerticalOptions="FillAndExpand">
<!--<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>-->
<Grid
x:Name="progressbar"
BackgroundColor="Transparent"
ColumnSpacing="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="Start">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
</Grid>
</StackLayout>
</ContentView>
My CodeBehind of custom control
public partial class CustomDashControl : ContentView
{
static int totalCount;
static Color barColor;
private static ObservableCollection<CustomControlData> tempData;
public static ObservableCollection<CustomControlData> TempData
{
get { return tempData; }
set
{
tempData = value;
customDashControl.OnPropertyChanged("TempData");
}
}
static CustomDashControl customDashControl;
public CustomDashControl()
{
try
{
InitializeComponent();
customDashControl = this;
}
catch (Exception ex)
{
BaseViewModel.HandleException(ex);
}
}
#region Bindable Properties
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource",
typeof(ObservableCollection<CustomControlData>),
typeof(CustomDashControl), new
ObservableCollection<CustomControlData>(),
BindingMode.Default, null, OnItemsSourceChanged);
private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
if (oldValue != newValue)
{
(bindable as CustomDashControl).OnPropertyChanged("ItemsSource");
TempData = (ObservableCollection<CustomControlData>)newValue;
UpdateBar();
}
}
private static void UpdateBar()
{
try
{
if (TempData != null && TempData.Count > 0)
{
var control = customDashControl.progressbar;
control.ColumnDefinitions.Clear();
control.Children.Clear();
//Working
for (int i = 0, j = 0; i < TempData.Count; i++, j++)
{
control.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
var tempBox = new BoxView() { Color = TempData[i].BarColor, WidthRequest = TempData[i].BarWidth };
control.Children.Add(tempBox, j, 0);
j++;
control.ColumnDefinitions.Add(new ColumnDefinition() { Width = 1 });
control.Children.Add(new BoxView() { Color = Color.White, WidthRequest = 1 }, (j), 0);
}
Console.WriteLine(control.Children);
}
}
catch (Exception ex)
{
BaseViewModel.HandleException(ex);
}
}
public ObservableCollection<CustomControlData> ItemsSource
{
get { return (ObservableCollection<CustomControlData>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly BindableProperty TotalCountProperty = BindableProperty.Create(propertyName: "TotalCount", returnType: typeof(int), declaringType: typeof(CustomDashControl), defaultValue: 0, propertyChanged: propertyChanges1);
private static void propertyChanges1(BindableObject bindable, object oldValue, object newValue)
{
if (oldValue != newValue)
{
var control = bindable as CustomDashControl;
totalCount = (int)newValue;
if (totalCount > 0)
{
(customDashControl.BindingContext as CustomDashControlViewModel).totalCount = totalCount;
}
}
}
public int TotalCount
{
get { return (int)GetValue(TotalCountProperty); }
set { SetValue(TotalCountProperty, value); }
}
#endregion
}
OnAppearing will be executed before the screen comes, when you want an Loaded event that needs to be executed right after the screen comes, there is a workaround.
Create an property in viewmodel like below.
private bool _toggleTemp;
public bool ToggleTemp
{
get => _toggleTemp;
set => SetProperty(ref _toggleTemp, value);
}
Add the following line to the last line of the constructor.
LoadingVm.ToggleTemp = true;
Add an Switch to your screen and make IsVisible to false as below.
<Switch IsToggled="{Binding ToggleTemp}" Toggled="Switch_OnToggled" IsVisible="False" />
Now you can write the code that you want to write in Page Loaded in Switch_OnToggled.
private async void Switch_OnToggled(object sender, ToggledEventArgs e)
{
/* Your code goes here... */
}
Thanks!
If this does not work refer this --
In the onappearing I wrapped everything in an async call and waited a few hundred ms for the page to get rendered.
await WaitAndExecute(1000, () =>
{
// refresh code
}
protected async Task WaitAndExecute(int milisec, Action actionToExecute)
{
await Task.Delay(milisec);
actionToExecute();
}
https://forums.xamarin.com/discussion/22561/page-loaded-event
I want to show a label when i click on my item in my listview.
The real problem i don't know how to link between my viewmodel and my views
I want modify my label in viewmodel but I don't know if its possible currently.
My xaml :
<StackLayout>
<Label x:Name="labelperso"
Text="{Binding newProduct}"
IsVisible="{Binding Addproduct}"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
BackgroundColor="#000000"
FontSize="20"
Opacity="0"/>
<ListView ItemsSource="{Binding Products}" CachingStrategy="RecycleElement" RowHeight="50" >
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding CodeReferenceLibelle}" TextColor="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemSelected" Command="{Binding
SelectCommand}" Converter="{StaticResource SelectedItemConverter}"/>
</ListView.Behaviors>
my viewmodel :
#region labelperso property
private string _newProduct;
public string newProduct
{
get { return _newProduct; }
set { SetProperty(ref _newProduct, value); }
}
#endregion
#region Addproduct property
private bool _Addproduct;
public bool Addproduct
{
get { return _Addproduct; }
set { SetProperty(ref _Addproduct, value); }
}
#endregion
when I click on my item :
async Task Select()
{
newProduct = "Produit ajouté !";
basketManager.AddProductSkuAsync(sku);
newProduct = "";
await Task.Run(() => ShowText());
}
//I have tried this but I can't use my label in my view
async Task ShowText()
{
await labelperso.FadeTo(1);
await Task.Delay(1000);
await labelperso.FadeTo(0);
}
Why are you want to take the label "labelperso" in VM ? you can use it in xaml.cs instead.
You just need to add the event ItemSelected like this:
<ListView ItemsSource="{Binding Products}" ItemSelected="OnSelection">
In xaml.cs
void OnSelection(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return;
}
//suppose the binding Object is Product
Product product = (Product)e.SelectedItem;
//labelperso.Text = "name = " + product.Name;
labelperso.FadeTo(1);
Task.Delay(1000);
labelperso.FadeTo(0);
}
Normally, VM are unrelated to Xaml, and we should not get labels from VM.
And we don't recommend it.But if you must, you can pass the Label in from the xaml.cs file like this:
You can define a variable in yourpage.xaml.cs:
public Label pageLabel;
and initial like this:
pageLabel = labelperso;
BindingContext = new YourViewmodel(this);
And in YourViewmodel.cs:
public Label ss;
public YourViewmodel(ContentPage parentPage)
{// here HomePage is your contentPage name of the page`
ss = ((HomePage)parentPage).pageLabel;//after this you can use it
}
You need to add a SelectedProduct property to your VM.
private string _SelectedProduct;
public string SelectedProduct
{
get { return _SelectedProduct; }
set { SetProperty(ref _SelectedProduct, value); }
}
You can then bind your ListView's SelectedItem to it
<ListView ItemsSource="{Binding Products}"
SelectedItem="{Binding SelectedProduct}"
CachingStrategy="RecycleElement"
RowHeight="50" >
You can then control the visibility of your label by binding to SelectedProduct via a "nullToVisibility" converter, or by using triggers etc.
You should try to use MVVM pattern rather than hacking with code behind.
Using MVVM you can add a Visible property to your viewmodel and bind the IsVisible property of the label to it.
Code will be much easy to read and maintain.
HI i try to reorder items in ItemsControl . when i set ManipulationMode of element in ItemsControl to ManipulationModes.TranslateY ScrollView dosent work. for this problem i change this ManipulationMode in Holding event but i faced a new problem.
in my code,we need release finger after holding and touch again for moving. i need holding and moving finger to drag items not holding and release and touch again and moving. this release is to bad for me and users
please help me.
my code:
<ItemsControl ItemsSource="{Binding Items}"
x:Name="todoList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Path=color, Converter={StaticResource ColorToBrushConverter}}"
Height="75"
x:Name="todoItem">
<i:Interaction.Behaviors>
<Behaviors:DragReOrderBehavior />
</i:Interaction.Behaviors>
<Grid Background="{StaticResource itemGradient}">
<!--task text-->
<TextBlock Text="{Binding Title}"
Margin="15,15,0,15" FontSize="25" TextWrapping="Wrap"
x:Name="taskText"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and behavior:
public class DragReOrderBehavior : DependencyObject, IBehavior
{
private static readonly int AutoScrollHitRegionSize = 80;
private DispatcherTimer _autoScrollTimer;
private FrameworkElement _dragItem;
private int _initialDragIndex;
private bool IsActive = false;
private ItemsControl itemscontrolList;
private ItemViewModel draggedItemVM;
private MainViewModel VM;
private ResettableObservableCollection<ItemViewModel> itemsListVm;
private ScrollViewer _scrollViewer;
// private SoundEffect _moveSound;
public DependencyObject AssociatedObject { get; private set; }
public void Attach(DependencyObject associatedObject)
{
AssociatedObject = associatedObject;
var fw = (FrameworkElement)AssociatedObject;
//fw.ManipulationMode = ManipulationModes.TranslateY | ManipulationModes.System;
////fw.ManipulationStarted += fw_ManipulationStarted;
fw.Holding += fw_Holding;
//fw.ManipulationDelta += fw_ManipulationDelta;
//fw.ManipulationCompleted += fw_ManipulationCompleted;
if (fw.RenderTransform == null || fw.RenderTransform as TranslateTransform == null)
{
fw.RenderTransform = new TranslateTransform();
}
// a timer which is used to periodically detect the position of the
// item being dragged in order to allow auto-scroll behaviour
_autoScrollTimer = new DispatcherTimer();
_autoScrollTimer.Interval = TimeSpan.FromMilliseconds(50);
_autoScrollTimer.Tick += (s, e) =>
{
AutoScrollList();
ShuffleItemsOnDrag();
};
// _moveSound = SoundEffect.FromStream(TitleContainer.OpenStream("Sounds/Windows XP Menu Command.wav"));
}
void fw_Holding(object sender, HoldingRoutedEventArgs e)
{
//if (Math.Abs(e.Cumulative.Translation.Y) > Math.Abs(e.Cumulative.Translation.X))
// {
//var fw = (FrameworkElement)AssociatedObject;
//fw.ManipulationMode = ManipulationModes.TranslateRailsY | ManipulationModes.System;
IsActive = true;
// locate the element being dragged
_dragItem = AssociatedObject as FrameworkElement;
itemscontrolList = AssociatedObject.Ancestors<ItemsControl>().OfType<ItemsControl>().FirstOrDefault();
draggedItemVM = ((ItemViewModel)_dragItem.DataContext);
VM = (MainViewModel)itemscontrolList.DataContext;
itemsListVm = VM.Items;
_scrollViewer = itemscontrolList.Descendants<ScrollViewer>()
.Cast<ScrollViewer>()
.SingleOrDefault();
_dragItem.SetVerticalOffset(0);
_dragItem.ManipulationMode = ManipulationModes.TranslateY;
_dragItem.ManipulationDelta += fw_ManipulationDelta;
_dragItem.ManipulationCompleted += fw_ManipulationCompleted;
_dragItem.UpdateLayout();
itemscontrolList.UpdateLayout();
_initialDragIndex = itemsListVm.IndexOf(draggedItemVM);
// fade out the items in the list, other than the dragged one
foreach (var item in itemscontrolList.GetItemsInView()
.Where(i => i.DataContext != draggedItemVM))
{
item.Animate(1.0, 0.7, "Opacity", 300, 0);
}
_autoScrollTimer.Start();
// }
}
}
The ListView & GridView support reordering items. How about thinking of using them?
First you can disable this feature by setting CanDragItems CanReorderItems AllowDrop to false and when you hold the item in your ListView then setting the properties above to true which will enable the Reorder feature.
I want to bind both the SelectedText and SelectedItem properties of an AutocompleteBox because my client wants to be able to input text and select from the list also. It's working properly but ...
The MainPage has one DataGrid. When I select a record from the Grid (i.e. SelectedItem), I want to set it in a popup window's AutocompleteBox. Some times it works but some times it doesn't.
What should I do for this issue?
This is my XAML:
<Sdk:AutoCompleteBox Grid.Column="3" Grid.Row="3" Height="18" Width="150"
IsTextCompletionEnabled="True" TabIndex="9" HorizontalAlignment="Left"
Text="{Binding ElementName=ResEdit,Path=DataContext.SelectedDemoText,Mode=TwoWay}"
ItemsSource="{Binding ElementName=ResEdit,Path=DataContext.DemoList,Mode=OneWay}"
ItemTemplate="{StaticResource DemoTemplate}"
ValueMemberPath="DemoCode"
LostFocus="AutoCompleteBox_LostFocus"
Margin="0,0,21,0" Padding="0">
</Sdk:AutoCompleteBox>
This property is in my view-model and bound to the DataGrid:
public InvoicesDTO SelectedInvoice
{
get { return _selectedInvoice; }
set
{
SelectedInvoice = value;
SelectedDomoText = SelectedInvoice.DemoText.Trim();
RaisePropertyChanged("SelectedInvoice");
}
}
You should not use both function SelectedText and SelectedItem in autocomplete. it's a bug of AutoCompleteBox..... A better way is to set the visiblity of the textbox and AutoCompleteBox on GotFocus and LossFocus. This Way You Will Defiantly Solve You Problem
private void DemoAutoComplete_LostFocus(object sender, RoutedEventArgs e)
{
DemoTextBox.Visibility = Visibility.Visible;
DemoAutoComplete.Visibility = Visibility.Collapsed;
DemoTextBox.Text = OCRAutoComplete.Text;
((DemoVM)this.DataContext).SelectedDemoText = DemoAutoComplete.Text;
}
private void DemoTextBox_GotFocus(object sender, RoutedEventArgs e)
{
DemoAutoComplete.Text = OctTextBox.Text;
DemoTextBox.Visibility = Visibility.Collapsed;
DemoAutoComplete.Visibility = Visibility.Visible;
DemoAutoComplete.Focus();
}