I have problem with DataContext in Windows Phone 8 project. When I run project and MainPage() is done - I see 1st GIF, but when I go Button_Click_1 - 1st GIF is still visible. I have no idea how DataContext work. Is there any way to set DataContext again and display 2nd GIF?
namespace PhoneApp1
{
public partial class MainPage : PhoneApplicationPage
{
public Uri ImageSource { get; set; }
// Constructor
public MainPage()
{
InitializeComponent();
ImageTools.IO.Decoders.AddDecoder<GifDecoder>();
ImageSource = new Uri("http://c.wrzuta.pl/wi7505/bcd026ca001736004fc76975/szczur-piwo-gif-gif", UriKind.Absolute);
this.DataContext = this;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ImageSource = new Uri("http://0-media-cdn.foolz.us/ffuuka/board/wsg/image/1338/94/1338947099997.gif", UriKind.Absolute);
this.DataContext = this;
}
}
}
XAML
<imagetools:AnimatedImage x:Name="Image" Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}" Margin="43,0,50,257" />
You will want to implement INotifyPropertyChanged so the Xaml knows of the changes to the ImageSource property.
Example:
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
private Uri _imageSource;
public Uri ImageSource
{
get { return _imageSource; }
set { _imageSource = value; NotifyPropertyChanged("ImageSource"); }
}
// Constructor
public MainPage()
{
InitializeComponent();
ImageTools.IO.Decoders.AddDecoder<GifDecoder>();
this.DataContext = this;
ImageSource = new Uri("http://c.wrzuta.pl/wi7505/bcd026ca001736004fc76975/szczur-piwo-gif-gif", UriKind.Absolute);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ImageSource = new Uri("http://0-media-cdn.foolz.us/ffuuka/board/wsg/image/1338/94/1338947099997.gif", UriKind.Absolute);
}
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notifies the property changed.
/// </summary>
/// <param name="property">The property.</param>
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
Related
Iam trying to change the image of the MainWindow's Grid, which is a room with no lights, by pressing a button on another Window, and come up with a room with lights background. The problem is that when i edit the onClick event of the button i cant change the MainWindow's Grid Background.
XAML of MainWindow's Grid:
<Grid x:Name="PIC">
<Grid.Background>
<ImageBrush ImageSource="lightsofflaptop.jpg"/>
</Grid.Background>
And the Window's Code:
public partial class Window3 : Window
{
public Window3()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
ImageBrush b1 = new ImageBrush();
b1.ImageSource = new BitmapImage(new Uri(#"---\lightsonNOlaptop.jpg"));
}
}
i cant connect b1 with the Grid Background of the MainWindow.
Thanks in advance.
**Edit
I navigate through Windows by this:
*button located in MainWindow.cs
private void button_Click(object sender, RoutedEventArgs e)
{
var newForm = new Window1();
newForm.Show();
this.Close();
}
It appears that you are a novice to WPF.
I would make a ViewModel and use this ViewModel in both Windows, and set the background property in Window3 and it will get reflected in MainWindow by Binding.
ViewModel
using System.ComponentModel;
using System.Windows.Media;
namespace WpfDatabase
{
public class ViewModel:INotifyPropertyChanged
{
private ImageBrush _background;
public ImageBrush Background
{
get { return _background; }
set { _background = value; OnPropertyChanged("Background"); }
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string prop)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
MainWindow.xaml
<Grid Background="{Binding Background}">
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public ViewModel VM
{
get { return this.DataContext as ViewModel; }
set { this.DataContext = value; }
}
public MainWindow()
{
this.VM = new ViewModel();
InitializeComponent();
this.VM.Background = new ImageBrush(new BitmapImage(new Uri(#"C:\Users\Public\Pictures\Sample Pictures\Koala.jpg")));
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Window3 win = new Window3(VM);
win.Owner = this;
win.Show();
}
}
Window3
public partial class Window3 : Window
{
public ViewModel VM
{
get { return this.DataContext as ViewModel; }
set { this.DataContext = value; }
}
public Window1(ViewModel vm)
{
InitializeComponent();
VM = vm;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.VM.Background = new ImageBrush(new BitmapImage(new Uri(#"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg")));
}
}
See this
If you are opening Window3 from the Window with the Grid that needs the image changed, you could pass a reference of the grid window in the constructor
Like this:
(In Window 3 Code)
private Window1 _parentWindow = null;
public Window3(Window1 parent)
{
_parentWindow = parent;
InitializeComponents();
}
private void button_Click(object sender, RoutedEventArgs e)
{
ImageBrush b1 = new ImageBrush();
b1.ImageSource = new BitmapImage(new Uri(#"---\lightsonNOlaptop.jpg"));
_parentWindow.PIC.Background = b1;
}
You could get a reference to the MainWindow using the Application.Current.Windows property.
You also need to make the "PIC" Grid field internal or public to be able to access it from another window. The easiest way to do this is to set the x:FieldModifier attribute in the XAML markup.
Try this:
MainWindow.xaml:
<Grid x:Name="PIC" x:FieldModifier="public">
<Grid.Background>
<ImageBrush ImageSource="lightsofflaptop.jpg"/>
</Grid.Background>
...
Window3.xaml.cs:
private void button_Click(object sender, RoutedEventArgs e)
{
ImageBrush b1 = new ImageBrush();
b1.ImageSource = new BitmapImage(new Uri(#"---\lightsonNOlaptop.jpg"));
MainWindow mw = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if(mw != null)
mw.PIC.Backgound = b1;
}
Hi I am following this tutorial,http://blogs.u2u.be/diederik/post/2011/11/14/null.aspx, to bind the visibility of an element to a Boolean property. The program is not working. Here is the code:
<Page.Resources>
<local:BooleanToVisibilityConverter x:Key="TrueToVisibleConverter"/>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBlock Text=" Hello World"
Visibility="{Binding Path=Show_element, Converter={StaticResource TrueToVisibleConverter}}"/>
<Button Click="Button_Click">press button</Button>
</StackPanel>
</Grid>
public sealed partial class MainPage : Page , INotifyPropertyChanged
{
private bool show_element ;
public bool Show_element
{
get { return show_element; }
set
{
show_element = value;
this.OnPropertyChanged();
Debug.WriteLine("Show_element value changed");
}
}
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Show_element = !Show_element;
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void OnPropertyChanged(string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class BooleanToVisibilityConverter : IValueConverter
{
public bool IsReversed { get; set; }
public object Convert(object value, Type typeName, object parameter, string language)
{
var val = System.Convert.ToBoolean(value);
if (this.IsReversed)
{
val = !val;
}
if (val)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
The visibility does not change with the property. I was having an error due to intellisense (Error Xaml namespace) which was resolved. Not sure what is wrong with this code.
Thank you.
change
this.OnPropertyChanged();
to
this.OnPropertyChanged("Show_element");
edit:
besides that, you don't have a ViewModel (sorry, missed that when I was checking your code), so you need to create one and set it as DataContext:
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
private bool show_element;
public bool Show_element
{
get { return show_element; }
set
{
show_element = value;
this.OnPropertyChanged("Show_element");
Debug.WriteLine("Show_element value changed");
}
}
public ViewModel()
{
}
public void ButtonClicked()
{
Show_element = !Show_element;
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void OnPropertyChanged(string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
and your MainPage.xaml.cs should look somehow like that:
public sealed partial class MainPage : Page
{
private ViewModel _viewModel;
public MainPage()
{
this.InitializeComponent();
_viewModel = new ViewModel();
DataContext = _viewModel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_viewModel.ButtonClicked();
}
}
this my xml code
<TextBlock Grid.Column="0" Tag="{Binding id,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Text="{Binding Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
this is my model
public string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; RaisePropertyChanged("Name"); }
}
when i set value to these two propertie ie. to id and Name
but its not notifying to Name ...
Simple Databinding Example with Updates. You can use this as a reference to get you started :)
public partial class MainWindow : Window, INotifyPropertyChanged
{
// implement the INotify
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _mytext;
public String MyText
{
get { return _mytext; }
set { _mytext = value; NotifyPropertyChanged("MyText"); }
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this; // set the datacontext to itself :)
MyText = "Change Me";
}
}
<TextBlock Text="{Binding MyText}" Foreground="White" Background="Black"></TextBlock>
I have a UserControl that I add to my main application.
That UserControl contains a button for a UIElement
The UserControl contains a DispatchTimer and every 2 seconds based on some int values determines what the button image will be.
One of the methods called in the UserControl should set it's image but the control never displays the image that it was changed to.
public void SetNormal()
{
btnFlashAlert.Content = new BitmapImage(new Uri("Images/FlashButton.png", UriKind.RelativeOrAbsolute));
}
Is there something i'm missing to get the look of the control update on the main application?
When I look at what .Content contains, it is correct. The UI doesn't reflect the change.
XAML
<UserControl x:Class="SC.FlashSystem.MainButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="53" Width="164">
<Button x:Name="btnFlashAlert" Background="{x:Null}" BorderBrush="{x:Null}" Cursor="Hand" Click="btnFlashAlert_Click">
<Button.Template>
<ControlTemplate>
<Image Source="Images/FlashButton.png"/>
</ControlTemplate>
</Button.Template>
</Button>
Codebehind Updated
public partial class MainButton : UserControl
{
private SupportConsoleWeb.MessageData messageCounts { get; set; }
private readonly DispatcherTimer flashButtonChangeTimer = new DispatcherTimer();
private BitmapImage NormalImage { get; set; }
private BitmapImage CriticalImage { get; set; }
private BitmapImage AlertImage { get; set; }
private BitmapImage InfoImage { get; set; }
public MainButton()
{
InitializeComponent();
messageCounts = new SupportConsoleWeb.MessageData();
messageCounts.CriticalCount = 0;
messageCounts.AlertCount = 0;
messageCounts.InfoCount = 0;
NormalImage = new BitmapImage(new Uri("Images/FlashButton.png", UriKind.RelativeOrAbsolute));
CriticalImage = new BitmapImage(new Uri("Images/FlashButtonRed.png", UriKind.RelativeOrAbsolute));
AlertImage = new BitmapImage(new Uri("Images/FlashButtonOrange.png", UriKind.RelativeOrAbsolute));
InfoImage = new BitmapImage(new Uri("Images/FlashButtonGreen.png", UriKind.RelativeOrAbsolute));
flashButtonChangeTimer.Interval = TimeSpan.FromSeconds(2);
flashButtonChangeTimer.Tick += flashButtonChangeTimer_Tick;
flashButtonChangeTimer.Start();
}
void flashButtonChangeTimer_Tick(object sender, EventArgs e)
{
btnFlashAlert.Dispatcher.BeginInvoke(new Action(() =>
{
if (btnFlashAlert.Content == null)
{
SetNormal();
}
else if (messageCounts.CriticalCount > 0 && btnFlashAlert.Content.Equals(CriticalImage))
{
SetNormal();
}
else if (messageCounts.AlertCount > 0 && btnFlashAlert.Content.Equals(AlertImage))
{
SetNormal();
}
else if (messageCounts.InfoCount > 0 && btnFlashAlert.Content.Equals(InfoImage))
{
SetNormal();
}
else if (messageCounts.CriticalCount > 0)
{
SetCritical();
}
else if (messageCounts.AlertCount > 0)
{
SetAlert();
}
else if (messageCounts.InfoCount > 0)
{
SetInfo();
}
}));
}
public void UpdateMessageCounts(SupportConsoleWeb.MessageData messageCounts)
{
this.messageCounts = messageCounts;
}
private void btnFlashAlert_Click(object sender, RoutedEventArgs e)
{
MainWindow window = new MainWindow();
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
window.ShowDialog();
}
public void SetMessageCount(int criticalCount, int alertCount, int infoCount)
{
messageCounts.CriticalCount = criticalCount;
messageCounts.AlertCount = alertCount;
messageCounts.InfoCount = infoCount;
}
private void SetNormal()
{
btnFlashAlert.Content = NormalImage;
}
private void SetCritical()
{
btnFlashAlert.Content = CriticalImage;
}
private void SetAlert()
{
btnFlashAlert.Content = AlertImage;
}
private void SetInfo()
{
btnFlashAlert.Content = InfoImage;
}
}
Change your XAML To this
<Image Source="{Binding TheImage}"/>
Add notify property changed
public partial class MainButton : UserControl, INotifyPropertyChanged
Create the OnPropertyChanged Event
void OnPropertyChanged(String prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
Create a Bitmap prop and notify the prop changed event
private BitmapImage _TheImage;
public BitmapImage TheImage
{
get { return _TheImage; }
set { _TheImage = value; OnPropertyChanged("TheImage"); }
}
In your initializer
public MainButton()
{
this.DataContext = this;
InitializeComponent();
TheImage = new BitmapImage();
Now in your setting methods call
TheImage = //Your Bitmap Goes here
I know this seems excessive but you will see it is a much cleaner implementation in the long run.
I believe its an issue with picture selection logic not having a default image when none of the conditions are met...
With that said, IMHO the picture logic would be better expressed by having all images pre-loaded and their visibility initially set to hidden. Then bind the visibility of each image to a specific flag boolean on the VM. Which the timer event can simply turn on or off the boolean(s) which will ultimately show or hide images as needed.
That removes any latency due to loading and showing of images for they will be pre-loaded; also it will solve any possible future memory issues due to loading/unloading of images.
Example
The following example has a button with two images. Both image's visibility is bound to Booleans on the VM. The VM has one Boolean which the imageas work off of and a timer which changes its status every two seconds switching the images.
Xaml:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<Button x:Name="bStatus" Width="48" Height="48">
<StackPanel Orientation="Vertical">
<Image Source="Images\Copy-icon.png" Visibility="{Binding IsCopyOn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<Image Source="Images\Recycle-icon.png"
Visibility="{Binding IsRecycleOn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</Button>
VM
public class MainVM : INotifyPropertyChanged
{
private bool _bSwitch;
private readonly DispatcherTimer flashButtonChangeTimer = new DispatcherTimer();
public bool IsRecycleOn
{
get { return _bSwitch; }
}
public bool IsCopyOn
{
get { return !_bSwitch; }
}
public MainVM()
{
flashButtonChangeTimer.Interval = TimeSpan.FromSeconds(2);
flashButtonChangeTimer.Tick += (sender, args) =>
{
_bSwitch = ! _bSwitch;
OnPropertyChanged("IsCopyOn");
OnPropertyChanged("IsRecycleOn");
};
flashButtonChangeTimer.Start();
}
/// <summary>Event raised when a property changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Raises the PropertyChanged event.</summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I am having a difficult time getting my WPF to properly use Databinding. In the XAML I have a the following:
....
<TextBox Name="txt_FirstName" Text="{Binding Path=currentApplication.FirstName, UpdateSourceTrigger=PropertyChanged}" />
....
I have in the following CS code:
namespace WPF1
{
public partial class MainWindow : Window
{
personalApp currentApplication = new personalApp ();
public MainWindow()
{
InitializeComponent();
}
}
}
That references the following two classes:
class personalApp : INotifyPropertyChanged
{
private Person person = new Person();
public string FirstName
{
get { return person.FirstName; }
set
{
person.FirstName = value;
this.OnPropertyChanged("FirstName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
class Person
{
private string firstName = "";
get { return firstName; }
set { FirstName = value; }
}
I pause it in the code and step through to check, but when I update the txt_FirstName in the application, it never seems to set the firstName Object.
Where am I going wrong?
You need to update your XAML binding, and set the DataContext of the Window using the TextBox.
namespace WPF1
{
public partial class MainWindow : Window
{
personalApp currentApplication = new personalApp ();
public MainWindow()
{
InitializeComponent();
this.DataContext = currentApplication;
}
}
}
Updating the XAML:
<TextBox Name="txt_FirstName" Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" />
I have corrected the code.
For text box:
<TextBox Name="txt_FirstName" Height="30" Background="Beige"
Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}" />
C# Code
namespace Wpf1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new personalApp();
}
}
internal class personalApp : INotifyPropertyChanged
{
private Person person = new Person();
public string FirstName
{
get { return person.FirstName; }
set
{
person.FirstName = value;
this.OnPropertyChanged("FirstName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
internal class Person
{
public string FirstName { get; set; }
}
}
public MainWindow()
{
DataContext = this;
InitializeComponent();
}
or if you don't want to assign data context to yourself (window), as you might have other datacontext coming into the window, you can add this in xaml:
give your window a name:
<Window .... x:Name="this"...
then
<TextBox Name="txt_FirstName" Text="{Binding ElementName=this,
Path=currentApplication.FirstName/>
What you mean by "update the txt_FirstName in the application" ?
If you set directly the value of the textbox then you should try to set the value of currentApplication instead of the textbox value