WPF - DataBinding (Command is not being executed) - wpf

I am writing a WPF application where I wish to implement the MVM pattern.
My code is currently set up like this:
This is my view model class where I am exposing the command I wish to be executed as a property
```
public HomeScreenViewModel(NavigationService mw)
{
this.mw = mw;
}
private RelayCommand _addStudent;
public ICommand AddStudent
{
get
{
if (_addStudent == null)
{
_addStudent = new RelayCommand(param => this.OpenNewStudents(), param => true);
}
return _addStudent;
}
}
This is my xaml containing the layout of the corresponding view
<Page x:Class="test.HomeScreen"
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"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="1300"
Title="HomeScreen">
<WrapPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<WrapPanel HorizontalAlignment="Center" Height="300" Margin="0,0,0,0" VerticalAlignment="Center" Width="1300">
<Button Content="AddStudent" Command="{Binding AddCommand}" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<Button Content="AddStudent" Style="{StaticResource ButtonStyle}" />
<TextBox Text="{Binding Path=HI}" Width="200" Height="200"/>
</WrapPanel>
<Canvas Margin="350, 100,0, 0" Height="300" Width="1350" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="Logo.PNG"/>
</Canvas>
</WrapPanel>
I have set the command of the top button using the binding syntax in the WrapPanel.
This HomeScreen page is linked from a naviagation window and is the source of the navigation window (xaml file):
<NavigationWindow x:Class="test.MainWindow"
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"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
Title="School Management App" Height="350" Width="1250"
Source="HomeScreen.xaml">
</NavigationWindow>
I have my HomeScreen view constructor set like this:
public partial class HomeScreen : Page
{
public HomeScreen()
{
InitializeComponent();
this.DataContext = new HomeScreenViewModel(this.NavigationService);
}
}
My infrastructure is set up as I have described above and my implementation of relay command is taken from this site https://msdn.microsoft.com/en-us/magazine/dd419663.aspx.
When I run my application and I press the corresponding button, nothing happens. I was wondering if someone could help me figure out what is wrong and why the command binding isn't working. It would be much appreciated, thanks :)
as a side note, could someone give me some tips on what the best way to debug wpf applications and figure out what bindings exist at run time.
Thanks :)

your command name is AddStudent, but you use AddCommand in xaml. Just correct the name:
Command="{Binding AddStudent}"

Related

Set binding on button tooltip with a declared instance of a user control as source

I've added a user control (with labels and textboxes) to my WPF project shown here:
<UserControl x:Class="MyProject.myControl"
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"
d:DesignHeight="384" Width="543">
<Grid x:Name="_LabelServerURL">
<Label x:Name="_LabelServerUrl" Content="Server Url:" HorizontalAlignment="Left" Margin="60,21,0,0" VerticalAlignment="Top" FontWeight="Bold"/>
<TextBox x:Name="_TextboxUrl" HorizontalAlignment="Left" Height="23" Margin="158,22,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="235"/>
<Label x:Name="_LabelURLExample" Content="(https://promodel.com)" HorizontalAlignment="Left" Margin="398,21,0,0" VerticalAlignment="Top" Width="139"/>
</Grid>
</UserControl>
and have created an instance of that user control in my main window code behind.
public partial class MainWindow : Window
{
private myControl _settings = new myControl();
public MainWindow()
{
InitializeComponent();
AddStackPanelChildren();
_ButtonEPSSettings.ToolTip = _epsSettings;
//SetButtonTootips();
}
In my main window I have a list of buttons, and I want to set their tooltip property (or bind the tooltip property) to the instance of my user control so that the tooltip dynamically updates when I add values to the textboxes in my user control. So far in my main window xaml I've been able to show my user control as the tooltip shown here:
<Window x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls ="clr-namespace:MyProject" <!--Declare project namespace-->
Title="EPS Configuration Manager" Height="415" Width="766">
<Grid>
<Button x:Name="_ButtonSettings"
Content="EPS Settings"
HorizontalAlignment="Left"
Margin="10,10,0,0"
VerticalAlignment="Top"
Width="199"
HorizontalContentAlignment="Left"
BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Click="_ButtonSettings_Click"
>
<Button.ToolTip>
<ToolTip>
<StackPanel HorizontalAlignment="Left" Height="384" Margin="0,0,0,0" VerticalAlignment="Top" Width="543" Name="_StackPanelEPSSettings">
<Controls:myControl/>
</StackPanel>
</ToolTip>
</Button.ToolTip>
</Button>
I am still not clear on setting that tooltip as the instance of my user control as declared in my main window code behind. Any help will go a long way. Thanks.
If you set tooltips in backgroud, don't use these code:
<Button.ToolTip>
<ToolTip>
<StackPanel HorizontalAlignment="Left" Height="384" Margin="0,0,0,0" VerticalAlignment="Top" Width="543" Name="_StackPanelEPSSettings">
<Controls:myControl/>
</StackPanel>
</ToolTip>
</Button.ToolTip>
If you want the tooltip dynamically updates:
private myControl mytooltip = new myControl();
public MainWindow()
{
InitializeComponent();
AddStackPanelChildren();
mytooltip._TextboxUrl.Text = "Hello";
_ButtonEPSSettings.ToolTip = mytooltip;
//SetButtonTootips();
}

xaml Scrollviewer - Disable Overscrolling / rubber-band-effect / snapback-effect / bouncing of whole window

When I'm using the a scrollviewer in a listbox, my whole window is bouncing when I reach the end of the listbox via touch scrolling. This behavior does not appear when I use my mouse wheel. How can I disable this overscrolling/ rubber-band-effect / snap-back-effect /bouncing effect.
I'm working with .NET Framework 4.5 on a Windows 8 Computer.
You can see the bounce effect on this video: http://www.vidup.de/v/gQ2pI/
Here is my example code:
<Window x:Class="style_test_for_scrollviewer.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>
<ListBox Width="200">
<WrapPanel Width="200" ScrollViewer.PanningMode="VerticalOnly" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible">
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
<Button Height="200" Width="200"></Button>
</WrapPanel>
</ListBox>
</Grid>
</Window>
You can remove this behavior by overriding the OnManipulationBoundaryFeedback method :
public class FixedListBox : ListBox
{
protected override void OnManipulationBoundaryFeedback(ManipulationBoundaryFeedbackEventArgs e)
{
e.Handled = true;
}
}
An other solution is to add the following handler to the ManipulationBoundaryFeedback event (directly on the ListBox or via a style):
<ListBox ManipulationBoundaryFeedback="OnManipulationBoundaryFeedback"/>
Or:
<Style TargetType="{x:Type ListBox}">
<EventSetter Event="ManipulationBoundaryFeedback" Handler="OnManipulationBoundaryFeedback"/>
</Style>
With the following code behind:
protected void OnManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
{
e.Handled = true;
}
Those methods works with the ScrollViewer too.

Prism not working in WP7.1 but working in WP8

I have developed a Windows Phone application using MVVM (Prism v4.1).
Everything is working fine when I deploy it to the Emulator WVGA or my HTC 8X but when I deply it to my Lumia 800 or use the Emulator 7.1 it isn't working.
Here is one part of the view(model) hope it helps a bit
View
<phone:PhoneApplicationPage
x:Class="LearnByTranslate.Views.PhrasePracticeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:converter="clr-namespace:LearnByTranslate.Infrastructure.Convverters"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<ScrollViewer Margin="24,0,24,72" Grid.Row="1">
<StackPanel x:Name="stkPracticeContent" Margin="0">
<TextBlock x:Name="txtTextToTranslate" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding EnglishPhrase,Mode=TwoWay}" FontSize="40" FontStyle="Normal" VerticalAlignment="Top" Style="{StaticResource EnglishSentenceStyle}" FontFamily="Segoe WP Light">
<TextBlock.Foreground>
<SolidColorBrush Color="{StaticResource PhoneForegroundColor}"/>
</TextBlock.Foreground>
</TextBlock>
</StackPanel>
</ScrollViewer>
</Grid>
</phone:PhoneApplicationPage>
ViewModel
class PhrasePracticeViewModel : NotificationObject
{
private string _englishPhrase;
public PhrasePracticeViewModel()
{
}
public string EnglishPhrase
{
get { return _englishPhrase; }
set
{
_englishPhrase = value;
RaisePropertyChanged(() => EnglishPhrase);
}
}
}
Everything is working fine (regarding the binding in the other views) except for this view.
Any ideas?
This is one of the strangest things I have ever seen.
The reasone for this was that my ViewModel class wasn't made public (as you can see above). I'll look into this a little deeper why this works on WP8 but not on WP7.1 but it really frustrated me.
Hope this helps someone else.

WPF command pattern

I have an application wide flag that is an app setting.
MyApp.Properties.Settings.Default.SoundMuted
The flag is if my apps sound is muted. I have a number of windows where sounds are being played through .Net’s sound player. I was thinking the flag would be wired up to a toolbar button with a command. I was thinking for muting notification to have my classes that play sound wire up to a class (e.g. SoundManager) hanging off the app that implements NotifyPropertyChange. Then if the user clicks the toolbar button, I would set the Muted property in my SoundManager and have all the soundplayer classes get the PropertyChange and mute.
Is there a better pattern for this? Say I could wire all the soundplayers up to the command and that command would fire.
Also is there some slick way to just wire that app setting as a bindable property in xaml?
Although I've always done the same approach as in my other answer in knocking up that example I have realized that it is unnesssasary. You can bind to the Settings object directly, like this:
<Window x:Class="Test_WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:Settings x:Key="SettingsRes"/>
</Window.Resources>
<Grid>
<Menu>
<MenuItem Header="Audio">
<MenuItem Header="Mute" IsCheckable="True"
IsChecked="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsRes}}"/>
</MenuItem>
</Menu>
<TextBlock Text="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsRes}}" Height="23" HorizontalAlignment="Left" Margin="18,156,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>
Again, multiple instances of that resource still work well together, e.g. bind the TextBlock to a second resource:
<Window x:Class="Test_WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:Settings x:Key="SettingsRes"/>
<local:Settings x:Key="SettingsRes2"/>
</Window.Resources>
<Grid>
<Menu>
<MenuItem Header="Audio">
<MenuItem Header="Mute" IsCheckable="True" IsChecked="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsRes}}"/>
</MenuItem>
</Menu>
<TextBlock Text="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsRes2}}" Height="23" HorizontalAlignment="Left" Margin="18,156,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>
One way is to make a wrapper class to provide bindable access to the static Settings.Default.
I have since realized this is more work than is needed, please see my other answer
namespace MyApp
{
internal sealed class ResourceWrapper
{
public Settings Default
{
get
{
return Settings.Default;
}
}
}
}
Now, we need to add that as a resource somewhere, could be done in App.xaml, here I've done local to the window that is using it, don't forget the namespace:
xmlns:local="clr-namespace:MyApp"
<Window.Resources>
<local:ResourceWrapper x:Key="SettingsWrapper"/>
</Window.Resources>
Now we need to bind to that, this shows it's use in a MenuItem on that same window:
<Menu>
<MenuItem Header="Audio">
<MenuItem Header="Mute" IsCheckable="True"
IsChecked="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsWrapper}}"/>
</MenuItem>
</Menu>
Like I said, you can add the resource at the app level or you can create multiple of these ResourceWrappers in different windows/controls, they will all point to the same static underneith.
That full xaml for window with a test TextBlock:
<Window x:Class="Test_WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ResourceWrapper x:Key="SettingsWrapper"/>
</Window.Resources>
<Grid>
<Menu>
<MenuItem Header="Audio">
<MenuItem Header="Mute" IsCheckable="True" IsChecked="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsWrapper}}"/>
</MenuItem>
</Menu>
<TextBlock Text="{Binding Path=Default.SoundMuted, Source={StaticResource ResourceKey=SettingsWrapper}}" Height="23" HorizontalAlignment="Left" Margin="18,156,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>

WPF binding root element of xaml file does not work:

I was trying to bind a dataContext to a grid (xaml below)
<Grid .... DataContext="{Binding Path=NewFormViewModel}" > ...</Grid>
This binding did not work and I realized the getter for NewFormViewModel was never being called.
At this point in time, The grid was the root element of the xaml file.
I then placed a canvas inside the Grid and did binding on the canvas like :
<Grid ....>
<Canvas DataContext="{Binding Path=NewFormViewModel}">
....
</Canvas>
</Grid>
The data binding worked.
Next I tried to change the grid to a canvas and do databinding agiain like this:
<Canvas.... DataContext="{Binding Path=NewFormViewModel}" > ...</Canvas>
The binding stopped working again.
In the end I settled for a Grid nested inside a canvas:
<Canvas....>
<Grid DataContext="{Binding Path=NewFormViewModel}">
....
</Grid>
</Canvas>
The question is why did the binding on the root element of the xaml not work?
or Should I have not used a Canvas/Grid as a root element at all and used something like Page/UserControl?
EDIT
My logical tree looks somthing like this:
Window <- Data binding to object o
|
*
Frame <-Data binding to obect o inherited
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel failed
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel Succeeds
EDIT2:
broken xaml:
<Canvas x:Class="WPFEditors.NewForm"
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="398" Width="377"
DataContext="{Binding Path=NewFormViewModel}"
>
<Grid >
<Label DataContext="Form Type" Height="31" HorizontalAlignment="Left" Margin="12,22,0,0" VerticalAlignment="Top" Width="92" />
<ComboBox Margin="148,22,6,347" ItemsSource="{Binding Path=FormTypes}" />
<Label Content="Description" Height="31" HorizontalAlignment="Left" Margin="12,58,0,0" VerticalAlignment="Top" Width="92" />
<Label Content="{Binding Path=Heading}" ToolTip="This is pulled from the Enum defined for FormTypes" Margin="148,59,6,309" />
<Label Content="Version" Height="31" HorizontalAlignment="Left" Margin="12,95,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Text="Bind this later" Margin="148,97,6,270" Height="31" />
<Label Content="Approval Level" Height="31" HorizontalAlignment="Left" Margin="12,132,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Height="31" Margin="148,134,6,233" Text="Bind this later" />
<Label Content="Number of Approvals" Height="31" HorizontalAlignment="Left" Margin="12,171,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,173,6,194" Text="Bind this later" />
<Label Content="Heading" Height="31" HorizontalAlignment="Left" Margin="12,210,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,212,6,155" Text="Bind this later" />
<Label Content="Static Data Id" Height="31" HorizontalAlignment="Left" Margin="12,247,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,249,6,118" Text="Bind this later" />
<Label Content="{Binding Path=Errors}" Background="{Binding Path=Color}" Margin="12,325,6,6" BorderThickness="1" BorderBrush="#FF000019" />
<Button Content="Create" Margin="83,294,202,78" />
<Button Content="Create" Margin="181,294,104,78" />
<Button Content="Create" Margin="279,294,6,78" />
</Grid>
</Canvas>
In the above xaml the following line binds:
<Label Content="{Binding Path=Heading}"
even though Heading is inside a property of the viewmodel that this document inherits.
At this point I would have expected the line:
DataContext="{Binding Path=NewFormViewModel}"
to have changed the datacontext to NewFormViewModel which has no heading. All the remaining bindings fail.
If I change the beginning to :
<Canvas x:Class="NewForm"
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="398" Width="377"
>
<Grid DataContext="{Binding Path=NewFormViewModel}" >
The binding to Heading fails and the rest of the bindings start to work. This is the behaviour that I was expecting initially.
This xaml is nested in this file :
<Window x:Class="WPFEditors.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Path=Heading}" Height="743" Width="1177">
<StackPanel >
<Menu IsMainMenu="True" >
<MenuItem Header="New">
<MenuItem Header="New Form" Command="{Binding Path=MenuCommand}" />
</MenuItem>
<MenuItem Header="Edit Form" ItemsSource="{Binding Path=FormsAvailable}" />
<MenuItem Header="Edit Rules" />
</Menu>
<Frame NavigationUIVisibility="Hidden" Source="{Binding Path=CurrentPage}"
LoadCompleted="Frame_LoadCompleted"
DataContextChanged="Frame_DataContextChanged"
Name="frame">
</Frame>
</StackPanel>
</Window>
and the event handlers to copy the data context to the child are :
private void Frame_LoadCompleted(object sender, NavigationEventArgs e)
{
UpdateFrameDataContext();
}
private void Frame_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
UpdateFrameDataContext();
}
private void UpdateFrameDataContext()
{
var content = frame.Content as FrameworkElement;
if (content == null)
return;
content.DataContext = frame.DataContext;
}
The Binding in the root element should work IF there is something up in the control hierarchy (like a Window or UserControl) that holds (in its DataContext) the object owning the property you're querying (NewFormViewModel).

Resources