How do i update UserControl textblock text from mainpage.xaml - windows-phone-8

I have textblock inside usercontrol.Now i want to update the text of textblock when i enter the text in mainpage.xaml.Please help
i tried this example but it does not update text.
UserControl.xaml
<TextBlock
x:Name="txtCartcount"
Text="{Binding CartCount}"
VerticalAlignment="Center"
FontWeight="Bold"
FontSize="15"
Foreground="#E4328A"
HorizontalAlignment="Center">
</TextBlock>
MainPage.xaml
private string _CartCount;
public string CartCount
{
get { return _CartCount; }
set { _CartCount = value; NotifyPropertyChanged("CartCount"); }
}
CartCount=txtMessage.text;

I'll suppose your user control contains other elements and not just the TextBox, if it's not the case, you can put your TextBox directly into your MainPage.xaml as it's easier.
Given that assumption, you have two options to change the text insideyour UserControl:
Without Binding: You should publicly expose a setter of your TextBox.Text property inside your UserControl so that you can modify it from your MainPage like this
myUserControl.SetText("MyText");
With binding: You should define a dependency property inside your user control that will wrap your TextBox.Text property. Then in the xaml of your main page you can bind this new defined property of your UserControl as if it was a TextBlock. Here's how you'd do this:
In your UserControl's codebehind:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text", typeof(String),typeof(UserControl), null
);
//This dependency property defined above will wrap the TextBlock's Text property
public String Text
{
get { return (String)GetValue(txtCartcount.Text); }
set { SetValue(txtCartcount.Text, value); }
}
Now your UserControl have a Bindable Text property that you can use in your MainPage.xaml like this:
<UserControl
Text = "{Binding PropertyToBindTo}"
</UserControl>
So now if you set up your binding correctly, when you change the bound property and fire up the NotifyChanged event, the defined Text property of your UserControl will get the notification and will call its setter, which will set the real Text property of your txtCartcount.
Hope this helps.

Related

Binding Mode OneTime in MvxRecyclerView

Is it possible to set the binding for one of my properties to be OneTime when the layout is used in a MvxRecyclerView? I set it to OneTime, but it keeps rebinding as I scroll through the list. This is the TextView that it keeps rebinding to:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/text_huge"
android:textColor="#color/white"
local:MvxBind="Text IsAddedToCart, Converter=BoolToFontAwesome, ConverterParameter=fa-shopping-cart|fa-cart-plus; Style ., Converter=String, ConverterParameter=fonts/fontawesome.ttf, Mode=OneTime" />
I set the binding mode to OneTime for the Style, but it keeps rebinding as I scroll through the items in the list (I know because I put a break point). This is the class for my Style binding:
public class StyleTextViewBinding : MvxAndroidTargetBinding
{
readonly TextView _textView;
public StyleTextViewBinding(TextView textView) : base(textView)
{
_textView = textView;
}
#region implemented abstract members of MvxConvertingTargetBinding
protected override void SetValueImpl(object target, object value)
{
var font = Typeface.CreateFromAsset(_textView.Context.Assets, value.ToString());
_textView.Typeface = font;
// I put a break point here, and I can see that it keeps rebinding
}
#endregion
public override Type TargetType
{
get { return typeof(string); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneTime; }
}
}
OneTime bindings will only work as such if you do not recycle your Views. Meaning if you don't scroll and change what is bound to the Style property from the ViewModel. Then it will only fire once.
Since RecyclerView uses the ViewHolder pattern, the views themselves are not recreated every time. This means, in order to have the correct state in the shown items, we need to re-bind them every time they reappear on the screen.

Not showing items with Visibility=Collapsed in Windows Phone 8.1 ListView

I have a problem with my ListView. I bind the ItemsSource to my ViewModel but I want items that have a certain property set to null to be completely collapsed (as in the whole item is collapsed, not just the control that is bound the the property that might be null). I have a converter that works but the ListView still seems to reserve at least some space for items that are collapsed. This results in my ListView having ugly "holes". (Please note that the holes do not take up as much space as the visible items but they do take up some space and the "invisible" items are even clickable...)
My problem is pretty much the same as the one stated here: Not showing items with Visibility=Collapsed in Windows 8.1 GridView
The only thing that bothers me is that the OP of the linked question says, that for him it's working fine in Windows Phone but not in Windows. Well for me it's not working in Windows Phone. Any suggestions what I could do?
The Code:
<DataTemplate x:Key="UpcomingEpisodesTemplate">
<Grid Visibility="{Binding Upcoming, Converter={StaticResource EpisodeVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
....The rest of the template which is not important...
</Grid>
</DataTemplate>
Thanks!
I have searched for 2 days to collapse items without the remaining place holder from the container style and this seems to work (WinRT 8.1).
(Key_Up Event from TextBox)
foreach (YourType element in TheListViewZoomedIn.Items)
{
if (!element.YourProperty.Contains(ListSearchBox.Text))
(TheListViewZoomedIn.ContainerFromItem(element) as ListViewItem).Visibility = Visibility.Collapsed;
}
It might not be super elegant or viable for huge lists but it does the job and offers tons of control. Just make sure to set the visibility again where you need to.
I just wanted to share this - it might help others in the future,
best regards,
Stefan
You could try convert whatever you binding to ItemsSource. Like this:
<ListView
ItemsSource={Binding MyList, Converter={StaticResource MyListConverter}}>
With converter like this.
public class MyListConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return ((IEnumerable<MyType>)value).Where(x => x.MyProperty != null);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return null;
}
}
Edit with ObservableCollection.
public class MyListConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var originalObservable = (ObservableCollection<MyType>)value;
var collection = new ObservableCollection<MyType>();
collection.AddRange(originalObservable.Where(x => x.MyProperty != null));
originalObservable.CollectionChanged += delegate { collection.Clear(); collection.AddRange(originalObservable.Where(x => x.MyProperty != null)); };
return collection;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return null;
}
}
In case if it helps, you can solve this issue with extra spaces of Collapsed ListViewItems by changing ItemContainerStyle to your custom style (edit a copy of default style) and change:-
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
<Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>
To
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>

LongListMultiSelector does not refresh the 2nd element's view when the count of ItemsSource is THREE

Recently I was using LongListMultiSelector(LLMS) in WPToolkit and now facing a quite strange bug. That is, when the ItemsSource of the LLMS has exactly 3 items. Then the second one's view doesn't get refreshed, while the other two do. And the LLMS is all right when the count is other than 3. I wrote a small App to test the situation. In this test, a LLMS is binding to an ObservableCollection<ItemViewModel>. Here is the code of ItemViewModel:
public class ItemViewModel : INotifyPropertyChanged
{
public ItemViewModel()
{
time = DateTime.Now;
}
private DateTime _time;
/// <summary>
/// Property for test use
/// </summary>
public DateTime time
{
get { return _time; }
set
{
if (_time != value)
{
_time = value;
RaisePropertyChanged("time");
}
}
}
#region INPC Impl
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string pName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(pName));
}
#endregion
}
And my LLMS is set like this:
<phone:PhoneApplicationPage.Resources>
<local:ItemToStrConverter x:Key="cvt"></local:ItemToStrConverter>
</phone:PhoneApplicationPage.Resources>
......
<toolkit:LongListMultiSelector Height="300" Name="llms">
<toolkit:LongListMultiSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource cvt}}"
Style="{StaticResource PhoneTextLargeStyle}"></TextBlock>
</DataTemplate>
</toolkit:LongListMultiSelector.ItemTemplate>
</toolkit:LongListMultiSelector>
The ItemToStrConverter is something that converts an instance of ItemViewModel to string (time.ToString()).
Please do notice that the Text of TextBlock in the DataTemplate is not binding to time. Instead, it is binding to the ItemViewModel instance directly.
So let's say if the LLMS is on the MainPage, and I go to some other pages to modify an ItemViewModel instance's time and go back to MainPage, this will cause the LLMS to be loaded and new one or more ItemToStrConverter to convert. If I have more or less than 3 items, everything is fine, all the instances will be converted properly. However, when I have 3 items, the second one does not get converted. I made a breakpoint in the Convert method, and the bug is occuring because this method was only called twice (to the 1st and 3rd instance). It seems that the LLMS simply ignores the 2nd instance.
Has anybody met this problem before?

LongListSelector.ItemTemplate Binding with IValueConverter receives parent viewmodel object instead of individual ItemsSource objects

For some reason, my LongListSelector is passing its inherited DataContext into my ItemTemplate converter causing the list items to display their default .ToString() value instead of my template.
I initially had the ItemTemplate defined as a Button control with a Template bound to a property of the items bound to the LongListSelector and that used an IValueConverter to grab the proper ControlTemplate:
ParentViewModel.cs
...
List<ChildViewModel> ChildViewModels { get; set; }
...
ChildViewModel.cs
...
MyEnumType MyEnumType { get; set; }
...
MainPage.xaml
<phone:LongListSelector x:Name="MyLongListSelector"
IsGroupingEnabled="False"
ItemsSource="{Binding ChildViewModels}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Button Template="{Binding MyEnumType, Converter={StaticResource MyConverter}}" DataContext="{Binding}"/>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
This worked fine, but I'm pretty sure I don't need to define a Button as the data template since I should be able to capture anything I need based on the selection event of the LLS.
So, trying to do it right (in my eyes; this is my first real WP8 App), I changed all my Templates from ControlTemplates to DataTemplates and updated my MyConverter to return DataTemplate objects based on the ChildViewModelProperty bound to the ItemTemplate:
public class MyConverter : IValueConverter
{
public object Converter(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
MyEnumType enumType = MyEnumType.DefaultType;
Enum.TryParse<MyEnumType>(value.ToString(), out enumType);
DataTemplate template = null;
switch (enumType)
{
case MyEnumType.Type1:
template = (DataTemplate)App.Current.Resources["MyEmumTypeTemplate1"];
break;
case MyEnumType.Type2:
template = (DataTemplate)App.Current.Resources["MyEnumTypeTemplate2"];
break;
default:
template = (DataTemplate)App.Current.Resources["MyEnumTypeTemplateDefault"];
break;
}
return template;
}
...
}
Then I updated my LongListSelector to bind the ItemTemplate directly to my ChildViewModelProperty of type MyEnumType with my MyConverter (declared in App.xaml as a static resource) converter as so:
<phone:LongListSelector x:Name="MyLongListSelector"
IsGroupingEnabled="False"
ItemsSource="{Binding ChildViewModels}"
ItemTemplate="{Binding MyEnumType, Converter={StaticResource MyConverter}}"
</phone:LongListSelector>
Now, when I view my app in the designer or in the emulator, my LongListSelector outputs a list with all of my elements presented as their .ToString() value (i.e. their fully qualified name).
What I've found is that ParentViewModel is being passed into MyConverter instead of each of the ChildViewModel.MyEnumType values. When I take out the specified Binding PropertyName (MyEnumProperty) and step through the debugger, value is of type ParentViewModel, the inherited DataContext of the LongListSelector. When I enter my desired Property name for the Binding, it simply fails the binding and doesn't even get into the Converter.
I saw a previous article that mentioned something about the LLS not handling a template change, but it had a comment (in 2011) that it's been fixed. I figured since it's 2013, it shouldn't be an issue anymore.
Am I missing something obvious, or do I need a go a little bit further? Or did I do it right in the first place with the Button?
Thanks for any help!
The issue is that when your binding is evaluated in the context of the LongListSelector as a whole and at that time the data context is the ChildViewModels. It is not reevaluated when implementing the individual item.
The approach I'd take to address your problem would be to implement a custom DataTemplateSelector that can choose the datatemplate based on the enum value.
<phone:LongListSelector x:Name="MyLongListSelector"
IsGroupingEnabled="False"
ItemsSource="{Binding ChildViewModels}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<MyDataTemplateSelector Content="{Binding}">
<MyDataTemplateSelector.Type1>
<DataTemplate>
// ... your content here
</DataTemplate>
</MyDataTemplateSelector.Type1>
<MyDataTemplateSelector.Type2>
<DataTemplate>
// ... your content here
</DataTemplate>
</MyDataTemplateSelector.Type2>
<MyDataTemplateSelector.Default>
<DataTemplate>
// ... your content here
</DataTemplate>
</MyDataTemplateSelector.Default>
</MyDataTemplateSelector>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
There's an example of how to implement such a selector at http://www.geekchamp.com/articles/implementing-windows-phone-7-datatemplateselector-and-customdatatemplateselector

Metro/Windows Store App: Relative Image Source Binding does not work?

I'm trying to create an ImageToggleButton for my WinRT project that changes it's image in respect to its IsChecked property.
In the designer of Visual Studio 2012 and Visual Studio Express for Windows 8 the ToggleButton behaves as expected, but during run time the image does not get displayed.
Any ideas?
XAML:
<Page.Resources>
<local:BooleanImageConverter x:Name="BoolImgConverter"/>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ToggleButton HorizontalAlignment="Left" Height="200" Margin="260,205,0,0" VerticalAlignment="Top" Width="833" Background="Yellow">
<Image Source="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Parent.IsChecked, Converter={StaticResource BoolImgConverter}, ConverterParameter=Assets/chkMusic}"/>
</ToggleButton>
</Grid>
CodeBehind:
public class BooleanImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string culture)
{
bool state = (bool)value;
string baseName = (string)parameter;
return string.Format("{0}_{1}checked.png", baseName, state ? "" : "un");
}
public object ConvertBack(object value, Type targetType, object parameter, string culture)
{
return null;
}
}
Code description:
I'd put an Image control into the ToggleButton and bind the image source to the IsChecked property of the containing (parent) ToggleButton using a converter that decorates the given ConverterParameter according IsChecked to provide the string to reference the desired image file.
Sure I could do this in code behind, but I would prefer to do it in XAML as much as possible.
At the moment I'm also not after building a ControlTemplate and I would have tried RelativeSource FindAncestor and other suggestions of this forum, but these dids not seem to work in Windows Store Apps (or am I wrong?).
I'd appreciate any suggestions.
Thanks
(BTW: I tried to add windows-store-app as tag to this post, but could not create this new tag - would someone else do this)
Parent has never worked as you think it would. There are a couple of ways to accomplish what you need.
The first is to keep the RelativeSource binding but remove the Path to IsChecked. This will pass the control to the converter. In it you can get the parent using the VisualTreeHelper.
The second is to name your ToggleButton and bind to it using ElementName binding
<ToggleButton x:Name="MusicToggle" HorizontalAlignment="Left" Height="200" Margin="260,207,-793,-207" VerticalAlignment="Top" Width="833" Background="Yellow">
<Image Source="{Binding IsChecked, ElementName=MusicToggle, Converter={StaticResource BoolToImage}, ConverterParameter=Assets/chkMusic}"/>