Cascaded command bindings possible - c#

I have a MainWindow that contains multiple views using MVVM. In fact the MainWindow holds only a list of Models and each time a Model is added it creates a View (here a UserControl) and associates the DataContext (Model) to the View. Each view is put into a separate TabItem in a TabControl.
The Model itself has a CommandBindingsCollection and assigns this command bindings to the View. This means that for example F10 is available multiple times, but should only the active View should react on F10.
But, F10 does not work at all. Only if I assign the CommandBinding to the MainWindow it works, but this makes the View dependent on the UserControl and this is not what I want, since I wnat to create the View as independent as possible from the MainWindow.
The only solution I have is to make this dynamically intercepting the change of the current TabItem and add/remove the commands for the active View. Currently everything works without code, but then I have to write code for it.
Attached is a code of the MainWindow:
<Window x:Class="WpfApplication3.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:WpfApplication3"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
</Window>
using System.Windows;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PluginControl aControl = new PluginControl();
Content = aControl;
}
}
}
and the code of the UserControl:
<UserControl x:Class="WpfApplication3.PluginControl"
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:WpfApplication3"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="White">
<StackPanel>
<Button Command="{Binding myCommand}" Content="PushMe" Focusable="False"/>
<Label Content="Nothing pressed" Name="myLabel"/>
</StackPanel>
</UserControl>
using System;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for PluginControl.xaml
/// </summary>
public partial class PluginControl : UserControl
{
public RoutedCommand myCommand
{
get;
private set;
}
public PluginControl()
{
InitializeComponent();
DataContext = this;
myCommand = new RoutedCommand();
myCommand.InputGestures.Add(new KeyGesture(Key.F10));
CommandBindings.Add(new CommandBinding(myCommand, myCommandHandler));
}
private void myCommandHandler(object sender, ExecutedRoutedEventArgs executed)
{
myLabel.Content = DateTime.Now.ToString();
}
}
}
As you see I have set the Button to Focusable false, since I want to have the command working in general, not only when the button is focused. I'm I missing something or thinking in a wrong direction, that making adding a CommandBinding does not implicitly mean that the command does work without binding it?
Adding the Command to the MainWindow itself works.
Any help?

Related

adding a list to itemsource, WPF

I am starting with WPF and I have this problem. I have a file called MainWindow.xaml with this code:
<Window x:Class="View.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:View" xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid >
<ItemsControl ItemsSource="{Binding}" x:Name="boardView">
</ItemsControl>
</Grid>
</Window>
And I have another file called MainWindow.xaml.cs with this code
namespace ViewModel
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var items = new List<string> { "a", "b", "c", "d", "e" };
}
}
}
Now I have to assign this list to boardView.ItemsSource. How can I do that?
You have four problems here that I can see that would need to get fixed for this to work.
In order for data binding to work, you need to set the DataContext of your MainWindow.
MainWindow.xaml.cs:
// Put this in the constructor after InitializeComponents();
this.DataContext = this;
Another requirement for data binding is to implement the INotifyPropertyChanged interface on the class you wish to having data binding (in your case this is MainWindow, but I recommend you read on MVVM design):
MainWindow.xaml.cs:
public partial class MainWindow : Window, INotifyPropertyChanged
Data bindings only work on public properties, so using var items isn't following this requirement. Instead, make var items a public property that updates itself with the PropertyChanged event whenever the value changes.
MainWindow.xaml.cs:
private List<string> items;
public List<string> Items
{
get => this.items;
set
{
this.items = value;
PropertyChanged?.Invoke(this, new PropertyName(nameof(Items)));
}
}
Lastly, you need to fix your binding in the xaml to bind to your public property.
MainWindow.xaml:
<ItemsControl ItemsSource="{Binding Items}" x:Name="boardView">

WPF dragblz Finding TabItem to Re-Add

ok Im not sure if this issue is related to the library or me being still being new to WPF .but , I'm using the dragablz library and I am trying to re-add a tab after tearing it then closing that specfic window. However , I cant seem to find all the TabItem when ever I try to search for it in the grid of the current winodw I get nothing , this what I treid.
<Window x:Class="TeheMan8_Editor.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:TeheMan8_Editor"
xmlns:dragablz="http://dragablz.net/winfx/xaml/dragablz"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<dragablz:TabablzControl Name="tabHub" AllowDrop="True" Grid.ColumnSpan="2">
<dragablz:TabablzControl.InterTabController>
<dragablz:InterTabController />
</dragablz:TabablzControl.InterTabController>
<TabItem Name="mainTab" Header="Tab No. 1" IsSelected="True">
<Button Click="Button_Click">Open FileButton</Button>
</TabItem>
</dragablz:TabablzControl>
</Grid>
</Window>
CSharp Code:
using DiscUtils.Iso9660;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace TeheMan8_Editor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var items = this.grid.Children.OfType<TabItem>(); //returns Empty
}
}
}
never mind I figured it out , the TabablzControl Object has a OfType function for the "Items.SouceCollection" property

How to set the public variable value from the wpf user control?

I have one dll which contains the wpf user control.
I have one wpf window in another wpf project which contains the above user control in that.
I have two public properties in wpf user control.
I want to set those properties from the wpf window in which wpf user control is added.
I have tried to do it using dependency property as follows :
TestUserControl.xaml :-
<UserControl x:Class="TestDependencyProperty.TestUserControl"
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="300" d:DesignWidth="300">
<Grid>
<Label Content="test property" x:Name="lblTestProperty"/>
</Grid>
</UserControl>
TestUserControl.xaml.cs :-
using System.ComponentModel;
using System.Windows;
namespace TestDependencyProperty
{
/// <summary>
/// Interaction logic for TestUserControl.xaml
/// </summary>
public partial class TestUserControl
{
public TestUserControl()
{
InitializeComponent();
SetLabelText();
}
private void SetLabelText()
{
lblTestProperty.Content = TestProperty;
}
public static readonly DependencyProperty TestDependencyProperty =
DependencyProperty.Register("TestProperty",
typeof(string),
typeof(TestUserControl));
[Bindable(true)]
public string TestProperty
{
get
{
return (string)this.GetValue(TestDependencyProperty);
}
set
{
this.SetValue(TestDependencyProperty, value);
}
}
}
MainWindow.xaml :-
<Window x:Class="TestDependencyProperty.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"
xmlns:local="clr-namespace:TestDependencyProperty"
>
<Grid>
<local:TestUserControl x:Name="ucTest" TestProperty="HelloWorld"/>
</Grid>
</Window>
I am expecting a label with content "HelloWorld".
So can anybody tell me how to do it ?
Thanks.
User Control XAML:
<UserControl x:Class="TestDependencyProperty.TestUserControl"
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:WpfApplication3"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="{Binding TestProperty}" x:Name="lblTestProperty"/>
</Grid>
</UserControl>
User Control Code:
public partial class TestUserControl : UserControl
{
public TestUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty TestDependencyProperty =
DependencyProperty.Register("TestProperty",
typeof(string),
typeof(TestUserControl));
[Bindable(true)]
public string TestProperty
{
get
{
return (string)this.GetValue(TestDependencyProperty);
}
set
{
this.SetValue(TestDependencyProperty, value);
}
}
}
You do not need SetLabelText();
Window Hosting User Control
<local:TestUserControl TestProperty="Test Text" x:Name="MyNewUserControl" />
in code behind if needed:
MyNewUserControl.TestProperty="New Value";
Dependency Properties have change notification built in to them so once a property is bound to them it will automatically get updated when the property does.

WPF ListView loses focus for every item

I'm having a little trouble with the WPF ListView and couldn't find any answer to this. I'm having a simple ListView in a WPF application with a few items in it. I have also attached a GotFocus event-handler on the GotFocus event. It seems that for every selection I do on the ListView also the GotFocus event is fired
xaml-code
<Window x:Class="WpfApplication4.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>
<ListView x:Name="MS" GotFocus="MS_GotFocus"></ListView>
</Grid>
cs-code
using System;
using System.Collections.Generic;
using System.Windows;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<string> test = new List<string>();
test.Add("Item 1");
test.Add("Item 2");
MS.ItemsSource = test;
}
private void MS_GotFocus(object sender, RoutedEventArgs e)
{
Console.WriteLine("Focus");
}
}
}
Has someone also experienced this problem?
Thanks
Martin

Access Class Variable in XAML

I have a class defined as:
class Constants
{
public static string settingsToolTip = "Settings";
}
I want to set this string for a tooltip of a button like:
<Button Name= "ButtonSettingsWindow" ToolTip="Settings" ToolTipService.ShowDuration="2000"/>
Instead of hardcoding the string "Settings" in XAML, I want it to use the string from Constants class. How can i do this in WPF XAML?
You can access static members of class using x:Static markup extension in XAML.
<Button ToolTip="{x:Static local:Constants.settingsToolTip}"/>
Make sure you have added namespace in XAML file (local) where Constant class is declared:
xmlns:local="clr-namespace:ActualNameSpace"
The answer you're looking for is binding.
Example:
Code behind:
class Test
{
public string test { get { return "Settings"; } }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<y:Test></y:Test>
</Window.DataContext>
<Grid>
<Button Content="{Binding test}"></Button>
</Grid>
The result is a button that says "Settings" :)

Categories