Update UserControl Textblock text from mainpage.xaml - xaml

I am writing a Windows Phone 8.1 Silverlight App. I made a user control NotificationsIconUserControl. It just contains a BELL/ALARM icon and textblock to display number of unread notifications.
I want to update this textblock text from mainpage.xaml
How to do this?
I tried using usercontrol expose properties but its the opposite thing. Also tried help from this question. how to use dependency property. Please edit the code below:
Usercontrol XAML:
<Grid x:Name="LayoutRoot"
Background="Transparent"
Height="Auto"
Width="Auto">
<Image
Name="Alarm_Icon"
Source="/Images/Status/Notification_Icon_1.png">
</Image>
<Ellipse
Name="Counter_Icon"
Height="45"
Width="45"
Margin="60,14,-6,50"
StrokeThickness="0"
Fill="{StaticResource DefaultTheme_IndianRedColor}">
</Ellipse>
<TextBlock
Name="Counter_Label"
Foreground="{StaticResource DefaultTheme_LightColor}"
FontSize="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
Margin="75,20,8,58"/>
</Grid>
Mainpage XAML part:
xmlns:MyUserControls="clr-namespace:Project.Custom.UserControls">
Mainpage .cs part:
private void ConfigureNotificationsIcon()
{
int NotificationsCounter = 4;
NotificationsIconUserControl NotificationsIconUserControlObject = new NotificationsIconUserControl();
NotificationsIconUserControlObject.Counter_Label.Text = NotificationsCounter.ToString();
}

I checked your code and its working completely....
ANd for the part of adding a Dependency property, write the following in the .cs file of UserControl
public partial class NotificationIconUserControl : UserControl
{
public NotificationIconUserControl()
{
InitializeComponent();
}
public string NotificationLabel
{
get { return (string)GetValue(NotificationLabelProperty); }
set { SetValue(NotificationLabelProperty, value); }
}
// Using a DependencyProperty as the backing store for Spacing. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NotificationLabelProperty =
DependencyProperty.Register("NotificationLabel", typeof(string), typeof(NotificationIconUserControl), new PropertyMetadata("hellllo"));
}
After that you can use TemplateBinding to do your job

Related

DataBinding inside data template in UWP

I have a usercontrol as follows which has DataTemplate. I want to bind the data inside the DataTemplate to a property inside the DataContext. In Uwp frustratingly they don't have ancestor type, how can I make my thing to work. I have refered this post UWP Databinding: How to set button command to parent DataContext inside DataTemplate but it doesn't work. Please help.
UserControl:
<local:CommonExpanderUserControl>
<local:CommonExpanderUserControl.ExpanderContent>
<DataTemplate x:DataType="Data:VmInstrumentSettingsLocal">
<StackPanel>
<TextBlock Text="{Binding LisLocalSettings.SomeText}"/>
<controls:ButtonBadged x:Name="ButtonApplyLisLocalChanges" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
x:Uid="/Application.GlobalizationLibrary/Resources/InstrumentSettingsViewButtonApply"
HorizontalAlignment="Center"
Margin="8"
Command="{Binding LisLocalSettings.SaveLisSettings}"/>
</StackPanel>
</DataTemplate>
</local:CommonExpanderUserControl.ExpanderContent>
</CommonExpanderUserControl>
In my UserControl xaml.cs as follows. I want to bind the button command to Command property inside the LisLocalSettings, but it won't work.
public InstrumentSetupLocalSettingsView()
{
this.InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty LisLocalSettingsProperty = DependencyProperty.Register(
nameof(LisLocalSettings),
typeof(VmInstrumentSettingsLisLocal),
typeof(InstrumentSetupLocalSettingsView),
new PropertyMetadata(default(VmInstrumentSettingsLisLocal)));
public VmInstrumentSettingsLisLocal LisLocalSettings
{
get => (VmInstrumentSettingsLisLocal) GetValue(LisLocalSettingsProperty);
set => SetValue(LisLocalSettingsProperty, value);
}
DataBinding inside data template in UWP
You could place Command in data source, but if the data source is collection, we need implement multiple command instance. In general, we place the command in current DataContext that could be reused. For the detail steps please refer the following.
<Page.Resources>
<DataTemplate x:Key="HeaderTemplate">
<StackPanel
x:Name="ExpanderHeaderGrid"
Margin="0"
Padding="0"
HorizontalAlignment="Stretch"
Background="Red"
Orientation="Vertical"
>
<TextBlock x:Name="TextBlockLisSharedSettingsTitle" Text="{Binding}" />
<Button Command="{Binding ElementName=RootGrid, Path=DataContext.BtnCommand}" Content="{Binding}" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid x:Name="RootGrid">
<uwpControls:Expander Header="hello" HeaderTemplate="{StaticResource HeaderTemplate}" />
</Grid>
Code Behind
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
public ICommand BtnCommand
{
get
{
return new CommadEventHandler<object>((s) => BtnClick(s));
}
}
private void BtnClick(object s)
{
}
}
public class CommadEventHandler<T> : ICommand
{
public event EventHandler CanExecuteChanged;
public Action<T> action;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
this.action((T)parameter);
}
public CommadEventHandler(Action<T> action)
{
this.action = action;
}
}

UWP One to many binding

i'm building venue navigation app, so i have two views, one is a list of possible destinations and the second is an jpg image with markers on top, so problem is:
on my model:
public class NavigationItem
{
public string Name {get; set;}
public string Icon{get; set;}
public List<Vector2> Location {get; set;}
}
on my viewmodel:
{
public List<NavigationItem> NavigationItems {get; set;}
}
now the xaml part
<ScrollViewer>
<Grid>
<Image Source="map.jpg/>
<winui:ItemsRepeater ItemsSource="{Binding NavigationItems}">
<DataTemplate>
<!-- And that's where the question is....
I can't just do Image Source Binding, because location is List<Vector2>-->
</DataTemplate>
</winui:ItemsRepeater>
</ScrollViewer>
So, i thought to make another items repeater nested in first one, but i have no clue how to propagate Image Source to it like so:
<winui:ItemsRepeater ItemsSource="{Binding NavigationItems}">
<DataTemplate>
<winui:ItemsRepeater DataContext="{Binding}" ItemsSource="{Binding Location}" >
<DataTemplate x:DataType="models:NavigationItemModel">
<Image Source="{Binding Icon}"/>
</DataTemplate>
</winui:ItemsRepeater>
</DataTemplate>
</winui:ItemsRepeater>
All i get just bunch of binding errors, guess i'll just a user control and spawn all the crap in code behind...
If you want to bind the Image Source with the Icon property, you need to change the DataContext of Image to the DataContext of the second ItemsRepeater. So you can subscribe the ElementPrepared event from ItemsRepeater which means this event occurs each time an element is made ready for use. So when triggered this event, you can change the DataContext of Image in it.
.xaml:
<winui:ItemsRepeater ItemsSource="{Binding NavigationItems}">
<DataTemplate>
<winui:ItemsRepeater ItemsSource="{Binding Location}" ElementPrepared="ItemsRepeater_ElementPrepared">
<DataTemplate>
<Image Source="{Binding Icon}"/>
</DataTemplate>
</winui:ItemsRepeater>
</DataTemplate>
</winui:ItemsRepeater>
.cs:
private void ItemsRepeater_ElementPrepared(Microsoft.UI.Xaml.Controls.ItemsRepeater sender, Microsoft.UI.Xaml.Controls.ItemsRepeaterElementPreparedEventArgs args)
{
var repeaterDataContext = sender.DataContext;
Image MyImage = args.Element as Image;
MyImage.DataContext = repeaterDataContext;
}

How to customize ListViewItem properly with hideable content and bind it to a model, in UWP?

I would like to create a ListView where items have a "hover" and a "selected" state, displaying different content in each state.
There have been some similar question here on StackOverflow, but none helped in my particular case.
Let's say I have a model:
public class TagFile : BaseBind // A class with INotifyProperyChanged interface
{
private string path;
public String Path
{
get { return path; }
set
{
SetProperty(ref path, value);
}
}
public void SelectButtonClick()
{
// Do something
}
public void HoverButtonClick()
{
// Do something
}
}
...then I have a main ViewModel:
public class AppViewModel : BaseBind
{
public ObservableCollection<TagFile> ItemsList { get; set; }
// Other things
}
... then a Page:
<Grid>
<ListView ItemsSource="ItemsList">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:TagFile">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{x:Bind Path, mode=OneWay}"/>
<Button Content="Select Button" Click="{x:Bind SelectButtonClick}"/>
<Button Content="Hover Button" Click="{x:Bind HoverbuttonClick}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
I would like to customize ListViewItem Style in order to make the SelectButton appear only when the ListViewItem is selected and the HoverButton only when the cursor is onto it.
I already know that I need to play with ItemTemplate and ItemContainerStyle, but it seems to be more difficult than I tought at the beginning, because I could create a custom style for the ItemContainerStyle in this way (using the IsSelected property from ListViewItem):
<Style TargetType="ListViewItem" x:Key="TestContainerStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentPresenter x:Name="Presenter" Content="{TemplateBinding Content}"/>
<Button Grid.Row="1" Content="Select Button" Visibility="{Binding IsSelected, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
...but in this way:
1) I loose all the default brushes;
2) I don't know how I could bind the SelectButton to the model's command;
3) I would have to find a way for the "hover" state, in order to display the HoverButton;
4) Last, but not least... I would like to include all the customizations in the App.xaml file (or in associated ResourceDictionary files, as I need them across the entire app).
This is it... I have tried various pattern from StackOverflow answers, but my case includes many differnt things (compile binding in App.xaml files, create a "hover" state, using binding in a Style without a DataType, etc.) that are answered here only separately.
I need to... put them all together, and it seems more tricky than I thought, as I said.
Thank you for your help, really appreciate.
EDIT: the behaviour should be like the Groove App list items: some buttons (Play and Remove item) appears only when the the item is selected or in hover state.
Normal state:
...and Hover/selected state:
There are two ways where you can achieve what you want:
The first one: I don't prefer it as you will need to copy the whole style and embed your item template inside the style. It also doesn't scale if you want to have the same behavior for multiple parts of your app.
You can copy the ListViewItem style which uses UIElement tree and visual states instead of a ListViewItemPresenter. This way you don't lose default brushes.
Note: look in the above link for the template with x:Key="ListViewItemExpanded".
<!-- Style for Windows.UI.Xaml.Controls.ListViewItem -->
<Style TargetType="ListViewItem" x:Key="ListViewItemExpanded">
Second Note:
These styles and resources are based on the Windows Software
Development Kit (SDK) for Windows 10, Version 1511 (Windows SDK
version 10.0.10586.0). Styles and resources from other versions of the
SDK might have different values. For design purposes, generic.xaml is
available in the (Program Files)\Windows
Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10586.0\Generic
folder from a Windows SDK installation.
Now you can use pointerover and selected states to show and hide different elements.
Second approach: Using custom control [Recommended]
Break your problem to two things:
You can define IsSelected property in your model/viewmodel for each item, and update that within your select command. Now you can control the first button visibility by binding to IsSelected.
Second is the hover part, you create a custom control which expose a dependency property IsPointerOver and you can bind visibility of the 'Hover Button' to it.
Example:
public class ExtendedControl : ContentControl
{
public static readonly DependencyProperty IsPointerOverProperty =
DependencyProperty.Register("IsPointerOver", typeof(bool), typeof(ExtendedControl),
new PropertyMetadata(false));
public bool IsPointerOver
{
get => (bool)GetValue(IsPointerOverProperty);
protected set => SetValue(IsPointerOverProperty, value);
}
protected override void OnPointerEntered(PointerRoutedEventArgs e)
{
base.OnPointerEntered(e);
IsPointerOver = true;
}
protected override void OnPointerCanceled(PointerRoutedEventArgs e)
{
base.OnPointerCanceled(e);
IsPointerOver = false;
}
protected override void OnPointerExited(PointerRoutedEventArgs e)
{
base.OnPointerExited(e);
IsPointerOver = false;
}
}
Xaml:
<ListView.ItemTemplate>
<DataTemplate >
<local:ExtendedControl x:Name="ExtendedControl">
<StackPanel>
<Button Content="Always Visible"/>
<Button Content="Only on hover" Visibility="{x:Bind ExtendedControl.IsPointerOver,Mode=OneWay,Converter={StaticResource BoolToVisibilityConverter}}"/>
</StackPanel>
</local:ExtendedControl>
</DataTemplate>
</ListView.ItemTemplate>

Two UserControls, one binds, one doesn't

I have two very simple UserControls in a simple WinRT demo project. No Viewmodel--mostly just colored boxes for layout exploration. The first UserControl I created works fine. The second, very similar one, won't bind to any properties--it shows up as blank.
The first UserControl looks like this:
<UserControl
x:Class="Demo.SmallStartTile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Demo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="SmallStartTileUC"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="SmallTileGrid"
Margin="0,0,8,8"
Background="{Binding Background, ElementName=SmallStartTileUC}"
>
<Rectangle
Stroke="{Binding BorderBrush, ElementName=SmallStartTileUC}"
Grid.RowSpan="2"
/>
<TextBlock x:Name="SmallTileTitle"
Text="{Binding TileText, ElementName=SmallStartTileUC}"
Style="{StaticResource SmallTileHeader}"/>
<Path x:Name="IconPath"
Style="{StaticResource SmallTileIcon}"
Data="{Binding TileIconPathData, ElementName=SmallStartTileUC}" />
</Grid>
</UserControl>
namespace Demo
{
public sealed partial class SmallStartTile : UserControl
{
public static DependencyProperty TileTextProperty = DependencyProperty.Register("TileText", typeof(string), typeof(SmallStartTile), new PropertyMetadata("tile content"));
public string TileText
{
get { return (string)GetValue(TileTextProperty); }
set { SetValue(TileTextProperty, value); }
}
public static DependencyProperty TileIconPathDataProperty = DependencyProperty.Register("TileIconPathData", typeof(string), typeof(SmallStartTile), new PropertyMetadata("F0"));
public string TileIconPathData
{
get { return (string)GetValue(TileIconPathDataProperty); }
set { SetValue(TileIconPathDataProperty, value); }
}
public SmallStartTile()
{
this.InitializeComponent();
}
}
}
And the second one, which I made just like the first one by clicking Add New Item and picking UserControl in Blend:
<UserControl
x:Class="Demo.SmallMediaTile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Demo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="SmallMediaTileUC"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid
Margin="0,0,8,8"
Background="{Binding Background, ElementName=SmallMediaTileUC}"
>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle
Stroke="{Binding BorderBrush, ElementName=SmallMediaTileUC}"
Grid.RowSpan="2"
/>
<Viewbox
Margin="30"
Child="{Binding Content, ElementName=SmallMediaTileUC}">
</Viewbox>
<TextBlock
Grid.Row="1"
Text="{Binding SourceText, ElementName=SmallMediaTileUC}"
Style="{StaticResource SmallMusicTileHeader}"/>
</Grid>
</UserControl>
namespace Demo
{
public sealed partial class SmallMediaTile : UserControl
{
public static DependencyProperty SourceTextProperty = DependencyProperty.Register("SourceText", typeof(string), typeof(SmallMediaTile), new PropertyMetadata("source"));
public string SourceText
{
get { return (string)GetValue(SourceTextProperty); }
set { SetValue(SourceTextProperty, value); }
}
public SmallMediaTile()
{
this.InitializeComponent();
}
}
}
I use the UserControl in the main Page like this:
<local:SmallMediaTile x:Name="Source1Tile"
Grid.Column="0" Grid.Row="0"
SourceText="Radio"
Background="Blue"
BorderBrush="Red">
<local:SmallMediaTile.Content>
<Canvas x:Name="radio_icon" Height="68" Width="34">
<Path Data="F1M299.6182,396.2988C299.6182,389.7208,297.0722,383.5548,292.4572,378.8398L288.6162,382.6758C292.2022,386.3718,294.1842,391.1778,294.1842,396.2988C294.1842,401.4238,292.2022,406.2368,288.6162,409.9328L292.4572,413.7738C297.0722,409.0538,299.6182,402.8808,299.6182,396.2988" Fill="White" Height="34.934" Canvas.Left="0" Stretch="Fill" Canvas.Top="16.501" Width="11.002"/>
<Path Data="F1M311.1738,396.2988C311.1738,386.6278,307.4348,377.5528,300.6788,370.6208L296.8258,374.4618C302.5658,380.3698,305.7398,388.0798,305.7398,396.2988C305.7398,404.5218,302.5658,412.2298,296.8258,418.1428L300.6788,421.9898C307.4348,415.0498,311.1738,405.9718,311.1738,396.2988" Fill="White" Height="51.369" Canvas.Left="8.21" Stretch="Fill" Canvas.Top="8.282" Width="14.348"/>
<Path Data="F1M322.7578,396.2988C322.7578,383.5298,317.8508,371.5348,308.9638,362.3388L305.1168,366.1748C312.9758,374.3538,317.3338,384.9778,317.3338,396.2988C317.3338,407.6208,312.9758,418.2488,305.1168,426.4268L308.9638,430.2748C317.8508,421.0698,322.7578,409.0798,322.7578,396.2988" Fill="White" Height="67.936" Canvas.Left="16.501" Stretch="Fill" Canvas.Top="0" Width="17.641"/>
</Canvas>
</local:SmallMediaTile.Content>
</local:SmallMediaTile>
The first one picks up all the properties and displays like I expect, but the second one only picks up the Viewbox content. I've looked through SO and been googling but can't figure out what the problem is. Sorry if this is longwinded.
Your root Grid is set as the Content of the UserControl while the Viewbox you have is trying to bind its Child property to the Content of the UserControl that is its ascendant. That is not allowed since the root Grid is already a parent of the UserControl and XAML controls can only exist in one place in the UI.
As noted, the problem is the UserControl's content can only be set once. When I bind the Viewbox Content to the UserControl content, the existing XAML is replaced. So, a blank box but for what I'm passing in. I guess to do what I had hoped, I'd need to make a custom control. Thanks for the help!

Windows Phone 7 XAML -- getting a binding to work with the container of my object

What I want to do is bind the text of a TextBlock to my custom ButtonSymbol property of the UserControl.
Here is the XAML for the UserControl. The Binding part for the TextBlock needs to be filled in.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Calculator.CalculatorButton"
d:DesignWidth="120" d:DesignHeight="80">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Image Source="buttonb#2x.png" Stretch="Fill"/>
<Button x:Name="InvisibleButton" Content="{Binding ButtonSymbol}" Margin="0,0,0,0" d:LayoutOverrides="Width, Height" BorderThickness="1" Click="InvisibleButton_Click"/>
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,0" TextWrapping="Wrap"
Text="{Binding ????????}"
VerticalAlignment="Top"/>
</Grid>
</UserControl>
And here is the CodeBehind:
namespace Calculator
{
public partial class CalculatorButton : UserControl
{
public string ButtonSymbol {get; set;}
public CalculatorButton()
{
// Required to initialize variables
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
}
private void InvisibleButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
Debug.WriteLine(#"click");
Debug.WriteLine(ButtonSymbol);
// TODO: Add event handler implementation here.
}
}
}
Note that this is WP7 with Silverlight, and the RelativeSource class is not the same as in other versions.
You need to set the DataContext of the user control.
If you add this:
this.DataContext = this;
into the constructor or Loaded event of the user control you can then do this:
Text="{Binding ButtonSymbol}"
Note that you can also declaratively bind the DataSource of the XAML, this is just an easy programmatic way to do it.