WPF ListBox Item BitmapImage Update - c#

I create a image edit software with images thumbnail viewer. I have a function that is Rotate image, user select a photo and click on button. The problem is i don´t want to refresh all the ListBox. So this code:
ImageListbox.Items.Refresh(); //Very slow if i have more than 100 imgs.
I Want a INotifyPropertyChanged just for BitmapImage.
XAML:
<ListBox Grid.Row="0" x:Name="ImageListbox" VirtualizingPanel.IsVirtualizing="true"
VirtualizingPanel.VirtualizationMode="Recycling" SelectionChanged="ImageListbox_SelectionChanged" MouseDoubleClick="ImageListbox_MouseDoubleClick"
ItemsSource="{Binding Path=Model}"
Background="AliceBlue" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Margin="0,0,2,0" Grid.RowSpan="2">
<ListBox.ContextMenu>
<ContextMenu x:Name="MenuContext">
<MenuItem Header="Abrir imagem (Prova)" Click="MenuItem_Click"/>
<MenuItem Header="Abrir imagem (Original)" Click="MenuItemOriginal_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="stack1" Height="330" Width="285" Margin="2,2,2,2" >
<WrapPanel>
<TextBlock Text="{Binding Path=ImgName}" Margin="5,0,0,0" FontSize="16" ></TextBlock>
<CheckBox Height="20" x:Name="chkUniqueId" IsChecked="{Binding Path=CheckBox}" Margin="5,0,0,0" Click="chkUniqueId_Click"/>
</WrapPanel>
<Image Margin="5,5,5,5" Height="300" Width="280" VerticalAlignment="Top" >
<Image.Source>
<BitmapImage x:Name="ImageSource" DecodePixelWidth="300" CacheOption="None" UriSource="{Binding Path=ImgPath}" />
</Image.Source>
</Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C#
public class ReportagemItems : ObservableCollection<ReportagemItem>
{
public ReportagemItems() { }
}
public class ReportagemItem : INotifyPropertyChanged
{
//i have more 2 properties here, not necessary for this example.
private string _ImgName;
public string ImgName
{
get { return this._ImgName; }
set
{
if (this._ImgName != value)
{
this._ImgName = value;
this.NotifyPropertyChanged("ImgName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
//in Btn Click event i have:
List<ReportagemItem> changeItem = ImageListbox.Items.OfType<ReportagemItem>().Where(x => x.CheckBox).ToList();
foreach (var item in Model.Where(x => x.ImgPath == changeItem.First().ImgPath))
{
item.CheckBox = false; //WORKS
item.ImgName = "New Name"; //WORKS
item.ImgPath = #"C:\Programa Provas\Destino\Performance15\Uteis\Thumb\1.JPG"; //DOESNT WORK...
}

Bind the Source property of the Image element, either directly to the source property:
<Image Margin="5,5,5,5" Height="300" Width="280" VerticalAlignment="Top" Source="{Binding Path=ImgName}"/>
...or by using a converter that creates and returns a BitmapImage: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ea1fd63b-738c-40ca-850e-994eb21dccea/binding-to-image-source-via-valueconverter-and-datacontext-in-usercontrol?forum=wpf

Related

Selecting close button of other tab closes current tab

I am creating an app where new tabs are created dynamically. I have added close button for each tab to close.
Issue:
If I have multiple tabs open, and I am currently in tab2, and I select close button of tab4, then tab2 get closed.
I have also used data binding of my TabControl using RelayCommand. But that also had the same issue.
Kindly suggest where I have gone wrong and what I can add in my code.
Below is my code.
XAML:
<TabControl x:Name="tabControl1" HorizontalAlignment="Stretch" MinHeight="50" Margin="0,0,0,0.2" Width="1215" ItemsSource="{Binding Titles, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="454" VerticalAlignment="Bottom">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="21">
<TextBlock Text="{Binding Header}" />
<Button Name="BtnClose" Content="X" Cursor="Hand" DockPanel.Dock="Right" Focusable="False" FontFamily="Courier" FontSize="9" FontWeight="Bold" Margin="0,1,0,0" Padding="0" HorizontalAlignment="Right" VerticalContentAlignment="Bottom" Width="16" Height="16"
Command="{Binding DataContext.CloseTabCommand,RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding ElementName=tabControl1,Path=SelectedItem}" />
<!--Click="BtnClose_Click"-->
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<RichTextBox Margin="10" VerticalScrollBarVisibility="Visible">
<FlowDocument>
<Paragraph FontSize="12" FontFamily="Courier New">
<Run Text="{Binding Content}"></Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
My ViewModel class where I create a class Tab Item "Item" that will hold a tab Content and header.
public class MainWindowViewModel: INotifyPropertyChanged {
public MainWindowViewModel() {
Titles = new ObservableCollection < Item > ();
}
public class Item: INotifyPropertyChanged {
public string Header {
get;
set;
}
//public string Content { get; set; }
private string _content;
public static int _count = -1;
public int Count {
get {
return _count;
}
set {
_count = value; /* OnPropertyChanged(nameof(Count));*/
}
}
public string Content {
get {
return _content;
}
set {
_content = value;
OnPropertyChanged(nameof(Content));
}
}
public Item() {
_count++; //increase the count of tab. This will represent the index of the tab
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
handler ? .Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public ObservableCollection < Item > Titles {
get {
return _titles;
}
set {
_titles = value;
OnPropertyChanged("Titles");
}
}
static int tabs = 1;
private ObservableCollection < Item > _titles;
private RelayCommand < Item > _closeTabCommand;
public RelayCommand < Item > CloseTabCommand {
get {
return _closeTabCommand ?? (_closeTabCommand = new RelayCommand < Item > (
(t) => {
Titles.Remove(t);
}));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
handler ? .Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml.cs
private void BtnClose_Click(object sender, RoutedEventArgs e) {
//remove tab
MainWindowVMObj.RemoveTabItem(tabControl1.SelectedIndex);
}
The close button's CommandParameter is passing the selected tab as the tab to be closed.
One easy fix to that is to simply bypassing the current source control of the event as a CommandParameter instead (which will be the parent TabItem of the targeted close button in that case):
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="21">
<TextBlock Text="{Binding Header}" />
<Button Name="BtnClose" Content="X" Cursor="Hand" DockPanel.Dock="Right" Focusable="False" FontFamily="Courier" FontSize="9" FontWeight="Bold" Margin="0,1,0,0" Padding="0" HorizontalAlignment="Right" VerticalContentAlignment="Bottom" Width="16" Height="16"
Command="{Binding DataContext.CloseTabCommand,RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>

display grid item position number in a grid observable collection

Below is my item template in a grid view.
</Grid.ColumnDefinitions>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SerialNumber}" VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="Bold" Margin="10" FontSize="25"/>
<TextBlock Text="." VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="Bold" FontSize="25" />
</StackPanel>
<Image Grid.Column="0" Margin="20" Height="100" Width="150" HorizontalAlignment="Center" Source="{Binding ImageUri,Mode=TwoWay}" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
what i am trying to achieve is to display the item position in the collection in the TextBlock Text="{Binding SerialNumber} (if this were to be a list view, it would be row number), please how do i achieve this.
You just need to define a class with the specific properties and bind it on xaml.
I made a simple code sample for your reference:
<GridView ItemsSource="{Binding oc}">
<GridView.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SerialNumber}" VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="Bold" Margin="10" FontSize="25"/>
<TextBlock Text="." VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="Bold" FontSize="25" />
</StackPanel>
<Image Grid.Column="0" Margin="20" Height="100" Width="150" HorizontalAlignment="Center" Source="{Binding source,Mode=TwoWay}" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
public sealed partial class MainPage : Page
{
public ObservableCollection<Test> oc { get; set;}
public MainPage()
{
this.InitializeComponent();
oc = new ObservableCollection<Test>();
oc.CollectionChanged += Oc_CollectionChanged;
for (int i=0;i<10;i++)
{
oc.Add(new Test() {SerialNumber=i,source=new BitmapImage(new Uri("ms-appx:///Assets/test.png")) });
}
this.DataContext = this;
}
private void Oc_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
for (int i =e.OldStartingIndex; i<oc.Count;i++)
{
oc[i].SerialNumber = i;
}
}
}
}
public class Test:INotifyPropertyChanged
{
private int _SerialNumber;
public int SerialNumber
{
get { return _SerialNumber; }
set
{
_SerialNumber = value;
RaisePropertyChanged("SerialNumber");
}
}
private BitmapImage _source;
public BitmapImage source
{
get { return _source; }
set
{
_source = value;
RaisePropertyChanged("source");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,new PropertyChangedEventArgs(PropertyName));
}
}
}

uwp gridview delete item with button within datatemplate

I have a gridview in UWP app and I have put a button in each gridview item in datatemplate so that it can be used to delete/remove that specific item from the gridview ( removing it from observableCollection behind). I am not using MVVM approach, because I am not much familiar with it, I am using a normal Observable Collection for binding of data and data template.
if you can suggest me a better way to do it, myabe using MVVM please suggest me how to do it. Thanks in advance
Code :
XAML GRID VIEW (button with the red back ground is the button I wanna use to delete item)
<controls:AdaptiveGridView Name="HistoryGridView" StretchContentForSingleRow="False"
Style="{StaticResource MainGridView}"
ItemClick ="HistoryGridView_SelectionChanged"
ItemsSource="{x:Bind HistoryVideos, Mode=OneWay}">
<controls:AdaptiveGridView.ItemTemplate>
<DataTemplate x:DataType="data:Video">
<StackPanel Margin="4" >
<Grid>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Style="{StaticResource TransparentButton}" Width="36">
<fa:FontAwesome Icon="Close" FontSize="20" HorizontalAlignment="Center" Foreground="White"
/>
</Button>
<Image Canvas.ZIndex="0" Source="{x:Bind Thumbnail}" Style="{StaticResource GridViewImage}"/>
<Border Style="{StaticResource TimeBorder}" Height="Auto" VerticalAlignment="Bottom"
Canvas.ZIndex="1"
HorizontalAlignment="Left">
<TextBlock Text="{x:Bind Duration}" Foreground="White" Height="Auto"/>
</Border>
</Grid>
<TextBlock Text="{x:Bind Name}" Style="{StaticResource GridViewVideoName}"/>
<TextBlock Text="{x:Bind ParentName}" Style="{StaticResource GridViewParentName}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock Text="{x:Bind Views}" Style="{StaticResource GridViewViews}"/>
<TextBlock Text="Views" HorizontalAlignment="Right"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>
Code Behind
public History()
{
this.InitializeComponent();
HistoryVideos = new ObservableCollection<Video>();
}
public ObservableCollection<Video> HistoryVideos { get; private set; }
I am using onnavigated to method for filling the collection and it works fine and also I guess that is not relevent here.
We can add the Command to the Button to invoke when this button is pressed and we can use parameter to pass to the Command property.
To use the Command, we should be able to define a DelegateCommand class that inherits from the ICommand.
For example:
internal class DelegateCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public DelegateCommand(Action<object> execute)
{
this.execute = execute;
this.canExecute = (x) => { return true; };
}
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
public void Execute(object parameter)
{
execute(parameter);
}
}
We can add the Id property in the Video, then we can pass the Id property to the CommandParameter. When we click the Button, the ExecuteDeleteCommand method will be fired. We can use the Id to find the Video in the HistoryVideos and use the Remove method to remove it.
The ViewModel code:
internal class ViewModel
{
private ObservableCollection<Viedo> _videos;
public ObservableCollection<Viedo> Videos
{
get
{
return _videos;
}
set
{
if (_videos != value)
{
_videos = value;
}
}
}
public ICommand DeleteCommand { set; get; }
private void ExecuteDeleteCommand(object param)
{
int id = (Int32)param;
Viedo cus = GetCustomerById(id);
if (cus != null)
{
Videos.Remove(cus);
}
}
private Viedo GetCustomerById(int id)
{
try
{
return Videos.First(x => x.Id == id);
}
catch
{
return null;
}
}
public ViewModel()
{
Videos = new ObservableCollection<Viedo>();
for (int i = 0; i < 5; i++)
{
Videos.Add(new Viedo());
Videos[i].Name = "Name";
Videos[i].Id = i;
}
this.DeleteCommand = new DelegateCommand(ExecuteDeleteCommand);
}
}
The XAML code:
<GridView Name="MyGridView" ItemsSource="{Binding Videos}">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"></TextBlock>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Width="36" Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
</Button>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The code behind:
private ViewModel myViewModel;
public MainPage()
{
this.InitializeComponent();
myViewModel = new ViewModel();
MyGridView.DataContext = myViewModel;
}
Update:
<GridView Name="MyGridView" ItemsSource="{x:Bind myViewModel.Videos}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:Viedo">
<StackPanel>
<TextBlock Text="{x:Bind Name}"></TextBlock>
<Button Background="Red"
HorizontalAlignment="Right" VerticalAlignment="Top"
Height="36" Canvas.ZIndex="1"
Width="36" Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
</Button>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>

MenuItem binding datacontext in listview

I have a ListView with a DataTemplate, inside this templates there are several textblocks and a button. The button has a contextmenu with fixed items. The binding of the listviewitems works fine, but binding a property to the contextmenu does not seem to work.
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid Grid.Column="0" Grid.RowSpan="2" Background="{Binding StateColor}">
</Grid>
<TextBlock Grid.Column="1" Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Anrufen" Name="mn_call" Click="mn_call_Click" DataContext={Binding Number} />
</ContextMenu>
</Button.ContextMenu> ...</Button>
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstEntry.KDKGRS}" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="{Binding FirstEntry.ConvertedKGFARBE}" />
<TextBlock Text="{Binding FirstEntry.ADNAMI}" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have removed some unnecessary bits of the code (style and columndefinitions) for readability.
The important part is the MenuItem inside the Button. My underlying class has a public string property Number. This should be passed to the menu item. But the DataContext of the MenuItem is always null inside the click event.
I've read something about the contextmenu not beeing part of the visual tree, but I can't wrap my head around it. Could somebody explain the issue with the binding?
Edit Code for the underlying class:
Again removed some unnecessary code for the question
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
And the binding of the ListBox:
List<PhoneClient> clients = new List<PhoneClient>();
clients = load(); //returns active Clients
lv_clients.ItemsSource = clients;
Bridging the gap
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Anrufen" Click="mn_call_Click" Name="mn_call"
DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
Handler
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
// Do Stuff
}
EDIT
MainWindow.xaml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="10">
<ListView x:Name="lv_clients" Margin="0 22 0 0" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="LightGray" Width="100">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Background="LightGreen">
</Grid>
<TextBlock Text="{Binding DisplayString}" Foreground="Black" Height="20" FontWeight="Bold" Padding="2,2,0,0" />
<Button Click="Button_ListItem_Click" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.ContextMenu>
<ContextMenu Tag="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Show" Click="mn_call_Click" Name="mn_call" DataContext="{Binding Tag.Number, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
</ContextMenu>
</Button.ContextMenu> ...
</Button>
<StackPanel Grid.Row="1">
<TextBlock Text="{Binding State}" Height="20" Padding="2,2,0,0"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Foo" Height="20" FontWeight="Bold" Padding="2,2,2,0" HorizontalAlignment="Left" Foreground="Blue" />
<TextBlock Text="Bar" Height="20" Padding="0,2,0,0" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
namespace WpfApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<PhoneClient> clients = new List<PhoneClient>();
clients.Add(new PhoneClient() { Name = "Kumar", Number = "0101010", Extension = "555", State = "New York" });
clients.Add(new PhoneClient() { Name = "Shanaya", Number = "1010101", Extension = "555", State = "New Jersey" });
clients.Add(new PhoneClient() { Name = "Billy Bob", Number = "6543210", Extension = "555", State = "Single" });
lv_clients.ItemsSource = clients;
}
public class PhoneClient
{
public String Name { get; set; }
public String Number { get; set; }
public String Extension { get; set; }
public String State { get; set; }
public String DisplayString
{
get
{
return String.IsNullOrEmpty(Name) ? Number : String.Format("{0} ({1})", Name, Extension);
}
}
}
private void mn_call_Click(object sender, RoutedEventArgs e)
{
MenuItem currentMenuItem = (MenuItem)sender;
string number = (string)currentMenuItem.DataContext;
MessageBox.Show("Number " + number);
}
private void Button_ListItem_Click(object sender, RoutedEventArgs e)
{
Button currentButton = (Button)sender;
PhoneClient data = (PhoneClient)currentButton.DataContext;
MessageBox.Show(data.Name + " tapped");
}
}
}

Button text template data binding is not working

I am developing my first Windows 8 app, in one page i am trying to update button text with latest timestop when page loads. I defined my xaml and codebehind like below:
I am using databinding to update the button text but it is not working as expected:
MainPage.xaml
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Button HorizontalAlignment="Left" Margin="333,284,0,0" VerticalAlignment="Top" Height="69" Width="162">
<Button.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding ButtonText}" VerticalAlignment="Top" Foreground="#FFFF6800" Height="34" Margin="-30,0,-22,-14" Width="115"/>
</Grid>
</DataTemplate>
</Button.Resources>
<Button.ContentTemplate>
<StaticResource ResourceKey="DataTemplate1"/>
</Button.ContentTemplate>
</Button>
</Grid>
MainPage.xaml.cs
public StatsClass Stats { get; private set; }
public MainPage()
{
this.InitializeComponent();
this.DataContext = Stats;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
UpdateButton();
}
private void UpdateButton()
{
if (Stats == null)
Stats = new StatsClass();
Stats.ButtonText = DateTime.Now.ToString();
}
StatsClass.cs
public class StatsClass : INotifyPropertyChanged
{
private string _buttonText;
public string ButtonText
{
get
{
return _buttonText;
}
set
{
_buttonText = value;
OnPropertyChanged("ButtonText");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
You have set Content of your Button twice, once with Content="Button" and again with.Button.ContentTemplate. You could just have:
<Button HorizontalAlignment="Left" Margin="333,284,0,0" VerticalAlignment="Top" Height="69" Width="162">
<Grid>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding ButtonText}" VerticalAlignment="Top" Foreground="#FFFF6800" Height="34" Margin="-30,0,-22,-14" Width="115"/>
</Grid>
</Button>
I had a similar issue yesterday using binding in a DataTemplate. I guess that you also had a binding error in the debug output.
I solved it using a relative source like that:
<TextBlock Text={Binding DataContext.ButtonText,
RelativeSource={RelativeSource FindAncestor, AncestorType=*YourControl*}}"/>
The Template has no direct access to the datacontext. By using the relative source you can bind to its properties.

Categories

Resources