Datacontext of usercontrol in TabItems inside another TabItems - c#

In my application I have a usercontrol called "ChannelControls" placed six times in six differents TabItems. The whole things is contains in an other tabcontrol. So basically, two levels of TabControls.
But since I've done that, all property stay empty and doesn't output anything. So I guess that's a datacontext problem.
Datacontext for the UserControl :
public partial class ChannelControls : UserControl
{
public ChannelControls()
{
InitializeComponent();
this.DataContext = this;
}
one of its property :
public static readonly DependencyProperty VidTranslateNamesProperty =
DependencyProperty.Register("VidTranslateNames", typeof(ObservableCollection<string>), typeof(ChannelControls));
[Bindable(true)]
public ObservableCollection<string> VidTranslateNames
{
get { return (ObservableCollection<string>)this.GetValue(VidTranslateNamesProperty); }
set { this.SetValue(VidTranslateNamesProperty, value); }
}
This is how the usercontrol is placed in one of the tabitems :
<Grid Grid.Row="1">
<TabControl x:Name="MainBoard" Style="{DynamicResource BaseTabControlStyle}" TabStripPlacement="Top" HorizontalContentAlignment="Center">
<TabItem x:Name="Channels" Header="CHANNELS" Style="{DynamicResource BaseTabItemStyle}" Background="{x:Null}" FontFamily="Bebas Neue Book" Margin="0" Height="30" Width="100" VerticalAlignment="Top" d:LayoutOverrides="Height">
<Grid x:Name="ChannelsContent" Margin="4, 4, 4, 4" DockPanel.Dock="Left">
<TabControl x:Name="ContentSelector" Style="{DynamicResource BaseTabControlStyle}" TabStripPlacement="Right" HorizontalContentAlignment="Center">
<TabItem x:Name="Channel0" IsSelected="True" Header="1" Style="{DynamicResource BaseTabItemStyle}" Height="45" Width="25" Background="{x:Null}" FontFamily="Bebas Neue Book">
<CMiX:ChannelControls Tag="0" VidTranslateNames="{Binding VideoTranslateNames, ElementName=cmix, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</TabItem>
</TabControl>
</Grid>
</TabItem>
</TabControl>
</Grid>

hmm why you have there :
ElementName=cmix
I working with static property mainly like this:
private static DependencyProperty _VidTranslateNamesProperty;
public static event EventHandler VidTranslateNamesPropertyChanged;
public static double VidTranslateNamesProperty
{
get { return _VidTranslateNamesProperty; }
set
{
_VidTranslateNamesProperty = value;
RaiseVidTranslateNamesPropertyChanged();
}
}
public static void RaiseVidTranslateNamesPropertyChanged()
{
EventHandler handler = VidTranslateNamesPropertyChanged;
if (handler != null)
handler(null, new EventArgs.Empty);
}
then you can bind it like
DependencyProperty ="{Binding Path=(local:Class.VidTranslateNamesProperty)}"

OK found the problem. Because I changed the name of the parent usercontrol, I forget to change ElementName everywhere I bind properties. As VisualStudio didn't raised any error, I needed time to find it...
Thank you anyway for the help.

Related

Give Name to Control inside a Object Dependency Property of an UserControl

I have an UserControl that have Object Propdp:
public partial class HeaderControl : UserControl
{
public HeaderControl()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty ControlContentProperty =
DependencyProperty.Register(nameof(ControlContent), typeof(object),
typeof(HeaderControl), new PropertyMetadata(null));
public object ControlContent
{
get { return (object)GetValue(ControlContentProperty); }
set { SetValue(ControlContentProperty, value); }
}
}
In Xaml file:
<Grid Grid.Row="1">
<ContentControl Content="{Binding ControlContent, ElementName=root}"/>
</Grid>
if i use it without give a Name to the Button inside it works:
<ctrl:HeaderContorl >
<ctrl:HeaderContorl.ControlContent>
<Button Content="Hallooo" FontSize="40"
Foreground="Black" Height="100"/>
</ctrl:HeaderContorl.ControlContent>
</ctrl:HeaderContorl>
But if i name the Button inside it not works:
<ctrl:HeaderContorl >
<ctrl:HeaderContorl.ControlContent>
<Button x:Name="Btn" Content="Hallooo" FontSize="40"
Foreground="Black" Height="100"/>
</ctrl:HeaderContorl.ControlContent>
</ctrl:HeaderContorl>
Can someone please tell me why I can't name the button inside?

How do I Data Bind between a TextBox and a Label in two different windows?

I have created a program that changes the text in a Label on the first window when you type in a TextBox on the second window. The idea is that I want to open a new window from my first window then on this new I want to type in a name and press a button to have that name be displayed on the first window. Am I making myself understood? Can anyone help me out? Thanks in advance!
The First Window(MainWindow)--
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
var createPlayerWindow = new CreatePlayerWindow();
DataContext = this;
createPlayerWindow.Show();
}
}
Xaml for MainWindow--
<Grid>
<Label x:Name="label2" Content="Name:" HorizontalAlignment="Left" Margin="10,63,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblName" Content="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="90,63,0,0" VerticalAlignment="Top"/>
<Button x:Name="button" Content="Create Player" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="81" Click="button_Click"/>
</Grid>
The Second Window(CreatePlayerWindow)--
public partial class CreatePlayerWindow : Window
{
public CreatePlayerWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
string playerName = txbName.Text;
Player player = new Player(playerName);
this.DataContext = player;
}
}
Xaml for CreatePlayerWindow--
<Grid>
<Label x:Name="label" Content="Name :" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txbName" HorizontalAlignment="Left" Height="23" Margin="63,12,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Create Player" HorizontalAlignment="Left" Margin="101,129,0,0" VerticalAlignment="Top" Width="88" Click="button_Click"/>
<Label x:Name="label1" Content="Class :" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top"/>
<ComboBox x:Name="cmbClass" HorizontalAlignment="Left" Margin="63,45,0,0" VerticalAlignment="Top" Width="120"/>
</Grid>
The Model(Player)--
public class Player : ViewModelBase
{
private string _name;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
OnPropertyChanged();
}
}
public Player(string name)
{
_name = name;
}
}
The ViewModel(ViewModelBase)--
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Have the main page's data context and the window's data context use the same instantiated VM which will have a Name property they both will use.
Then in xamls bind appropriately to the Name property on the VM which will adhere to the INotifyPropertyChange notification so that when it changes it will update the other item.
Don't forget that on the editing XAML the binding Mode should be TwoWay otherwise the user changes will not be seen.
Your MainWindow needs a ViewModel for its databinding. DataContext = this is useless here. So create a new class with a PlayerName property (with backing field), instanciate it in MainWindow constructor and set the main windows databinding to it. In the setter call OnPropertyChanged after setting the backingfield to value. Bind your label to the PlayerName property.
In your click event, you should create a viewmodel(player-)instance of your createplayerwindow and bind it to the createplayerwindow-instance's datacontext. add the missing databindings in your createplayerwindow to update your viewmodel (twoway). Replace the Show() method invocation in your button click event with ShowDialog(). After ShowDialog invokation call the new properties setter with the viewmodel.name value.

How to create resuable control and set the properties of nested controls using common template/control in xaml

I have tried to google this but I am not super clear on the suggestions I see people making.
I have 3 buttons within a user control that are exactly the same except for automation id and text. Instead of duplicating this code across all buttons, I would like to create a common control or control template that I can use. My problem is these buttons have nested controls whose text I need to change but I'm not sure how to do this.
<UserControl>
<Grid>
<StackPanel x:Name="myStackPanel" Grid.Row="1" Padding="0">
<Button AutomationProperties.AutomationId="CallButton" x:Name="CallButton" Style="{StaticResource ButtonStyle}">
<RelativePanel>
<SymbolIcon AutomationProperties.AutomationId="CallIcon" x:Name="CallIcon" Symbol="Phone" Style="{StaticResource SymbolStyle}" />
<StackPanel>
<TextBlock AutomationProperties.AutomationId="CallLabel" Text="Call" Style="{StaticResource LabelStyle}"/>
<TextBlock AutomationProperties.AutomationId="CallText" Text="123-456-7890" Style="{StaticResource ContentStyle}"/>
</StackPanel>
</RelativePanel>
</Button>
<Button AutomationProperties.AutomationId="EmailButton" x:Name="EmailButton" Style="{StaticResource ButtonStyle}">
<RelativePanel>
<SymbolIcon AutomationProperties.AutomationId="EmailIcon" x:Name="EmailIcon" Symbol="Mail" Style="{StaticResource SymbolStyle}"/>
<StackPanel >
<TextBlock AutomationProperties.AutomationId="EmailLabel" Text="Email" Style="{StaticResource LabelStyle}"/>
<TextBlock AutomationProperties.AutomationId="EmailText" Text="meetme#email.com" Style="{StaticResource ContentStyle}"/>
</StackPanel>
</RelativePanel>
</Button>
<Button AutomationProperties.AutomationId="WebsiteButton" x:Name="WebsiteButton" Style="{StaticResource ButtonStyle}">
<RelativePanel>
<SymbolIcon AutomationProperties.AutomationId="WebsiteIcon" x:Name="WebsiteIcon" Symbol="Link" Style="{StaticResource SymbolStyle}"/>
<StackPanel >
<TextBlock AutomationProperties.AutomationId="WebsiteLabel" Text="Website" Style="{StaticResource LabelStyle}"/>
<TextBlock AutomationProperties.AutomationId="WebsiteText" Text="http://meetme.com" Style="{StaticResource ContentStyle}"/>
</StackPanel>
</RelativePanel>
</Button>
</StackPanel>
</Grid>
</Grid>
As you can see, the code for all 3 buttons is same. All I want to do is create a control where I can set the automation ids and text properties of the nested controls.
Thanks!
You can create a button based on a UserControl (add a new UserControl). It will allow you to enjoy all the default button's properties, events and states (OnClick, Command, etc.) and to add your own properties, template and behavior.
Using dependency properties instead of simple properties is strongly advised if you want to use bindings or animations on them.
C#:
public partial class CustomButton : Button
{
#region IconAutomationId
public string IconAutomationId
{
get { return (string)GetValue(IconAutomationIdProperty); }
set { SetValue(IconAutomationIdProperty, value); }
}
public static readonly DependencyProperty IconAutomationIdProperty =
DependencyProperty.Register("IconAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));
#endregion
#region LabelAutomationId
public string LabelAutomationId
{
get { return (string)GetValue(LabelAutomationIdProperty); }
set { SetValue(LabelAutomationIdProperty, value); }
}
public static readonly DependencyProperty LabelAutomationIdProperty =
DependencyProperty.Register("LabelAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));
#endregion
#region TextAutomationId
public string TextAutomationId
{
get { return (string)GetValue(TextAutomationIdProperty); }
set { SetValue(TextAutomationIdProperty, value); }
}
public static readonly DependencyProperty TextAutomationIdProperty =
DependencyProperty.Register("TextAutomationId", typeof(string), typeof(CustomButton), new PropertyMetadata(null));
#endregion
#region Symbol
public object Symbol
{
get { return (object)GetValue(SymbolProperty); }
set { SetValue(SymbolProperty, value); }
}
public static readonly DependencyProperty SymbolProperty =
DependencyProperty.Register("Symbol", typeof(object), typeof(CustomButton), new PropertyMetadata(null));
#endregion
#region Label
public string Label
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty LabelProperty =
DependencyProperty.Register("Label", typeof(string), typeof(CustomButton), new PropertyMetadata(null));
#endregion
#region Text
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(CustomButton), new PropertyMetadata(null));
#endregion
public CustomButton()
{
InitializeComponent();
}
}
XAML:
<Button x:Class="WpfApplication1.CustomButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="customButton">
<RelativePanel>
<SymbolIcon AutomationProperties.AutomationId="{Binding IconAutomationId, ElementName=customButton}"
Symbol="{Binding Symbol, ElementName=customButton}"
Style="{StaticResource SymbolStyle}"/>
<StackPanel >
<TextBlock AutomationProperties.AutomationId="{Binding LabelAutomationId, ElementName=customButton}"
Text="{Binding Label, ElementName=customButton}"
Style="{StaticResource LabelStyle}"/>
<TextBlock AutomationProperties.AutomationId="{Binding TextAutomationId, ElementName=customButton}"
Text="{Binding Text, ElementName=customButton}"
Style="{StaticResource ContentStyle}"/>
</StackPanel>
</RelativePanel>
</Button>
Use:
<local:CustomButton AutomationProperties.AutomationId="CallButton"
x:Name="CallButton"
Style="{StaticResource ButtonStyle}"
IconAutomationId="CallIcon"
LabelAutomationId="CallLabel"
TextAutomationId="CallText"
Symbol="Phone"
Label="Call"
Text="123-456-7890"/>
It may be more work than you feel like doing but it sounds like you're going to want to create a UserControl. It should inherit from Button in the code-behind:
public partial class MyButton: Button
In the XAML you will include essentially the guts of what you have in each of the buttons now.
The tedious part is that you will then (in the code-behind) need to create a DependencyProperty for each of the "properties" you will want to set in this control: for example, one for the CallIconAutomationId, one for the CallLabelAutomationId, one for the CallLabelText, etc. You will then bind each of these properties in the XAML to the dependency property. These properties become the data that you will set on each individual MyButton (your new UserControl).
Then, in the container that is hosting these controls (which appears to be another UserControl in your example above) you would set these custom properties on each of your new MyButton controls, which will look something like this:
<myNamespace:MyButton EmailIconAutomationId="EmailIcon" LabelAutomationId="EmailLabel" />
etc.
Basically, you're creating a new control (a UserControl) based on the Button control (which gives you most of your functionality) and adding new custom properties directly to that new control (which work just like all the other control properties you're accustomed to).

How to create a custom Textbox with a TextBlock?

I want to create a custom control(or user control) which has both a textblock and a textbox as in the fig below:
Both the textblock and Textbox text properties are to be bound to the database fields and be able to apply styling etc. Which is the best approach for the same?
I have come up with a solution as below:
XAML for user control:
<UserControl x:Class="TestDependency.TextBlox"
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"
x:Name="abc"
DataContext="{Binding RelativeSource={RelativeSource Self}}" >
<Grid Width="170">
<TextBlock Height="23" HorizontalAlignment="Left" Margin="0,1,0,0"
Text="{Binding Path=Caption}"
VerticalAlignment="Top" Width="52" />
<TextBox Height="25" HorizontalAlignment="Left" Margin="53,-2,0,0"
x:Name="TextBox1"
Text="{Binding Path=Value}"
VerticalAlignment="Top" Width="120" />
</Grid>
Code behind for Usercontrol:
public partial class TextBlox : UserControl
{
public TextBlox()
{
InitializeComponent();
}
public static DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(TextBlox));
public static DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(TextBlox));
public string Caption
{
get
{
return (string)GetValue(CaptionProperty);
}
set
{
SetValue(CaptionProperty, value);
}
}
public string Value
{
get
{
return (string)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
}
}
static void ValueChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args)
{
TextBlox inst = (TextBlox)property;
inst.TextBox1.Text = (string)args.NewValue;
}
}
XAML for actual form where Usercontrol is used:
<Grid x:Name="grdmain">
<my:TextBlox Caption="{Binding XValue, Mode=TwoWay}" Value="{Binding WindowName, Mode=TwoWay}"
HorizontalAlignment="Left" Margin="246,197,0,0" x:Name="textBlox1" VerticalAlignment="Top" />
</Grid>
Code behind:
public partial class MainWindow : Window
{
DataEntities dt = new DataEntities();
CoOrdinate oCord;
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
oCord = dt.CoOrdinates.First();
grdmain.DataContext = oCord;
}
}
Still the binding doesnt work. But the code :
textBlox1.Caption = "test";
is working fine. where am I wrong?
Create an user control with a textblock and textbox and bind the values to that control.
<YourUserControl TextBlockText="{Binding TextBlockText}" TextBoxText="{Binding TextBoxText, Mode=TwoWay}"/>

WPF checkbox binding

While it is trivial to store a checkbox's checked state in a variable using the checkbox's Click event, how would I do it via databinding? All the examples I have found have the UI updated from some datasource, or bind one control to another; I want to update a member variable when the checkbox is clicked.
TIA for any pointers...
You must make your binding bidirectional :
<checkbox IsChecked="{Binding Path=MyProperty, Mode=TwoWay}"/>
You need a dependency property for this:
public BindingList<User> Users
{
get { return (BindingList<User>)GetValue(UsersProperty); }
set { SetValue(UsersProperty, value); }
}
public static readonly DependencyProperty UsersProperty =
DependencyProperty.Register("Users", typeof(BindingList<User>),
typeof(OptionsDialog));
Once that is done, you bind the checkbox to the dependency property:
<CheckBox x:Name="myCheckBox"
IsChecked="{Binding ElementName=window1, Path=CheckBoxIsChecked}" />
For that to work you have to name your Window or UserControl in its openning tag, and use that name in the ElementName parameter.
With this code, whenever you change the property on the code side, you will change the textbox. Also, whenever you check/uncheck the textbox, the Dependency Property will change too.
EDIT:
An easy way to create a dependency property is typing the snippet propdp, which will give you the general code for Dependency Properties.
All the code:
XAML:
<Window x:Class="StackOverflowTests.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" x:Name="window1" Height="300" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<CheckBox Margin="10"
x:Name="myCheckBox"
IsChecked="{Binding ElementName=window1, Path=IsCheckBoxChecked}">
Bound CheckBox
</CheckBox>
<Label Content="{Binding ElementName=window1, Path=IsCheckBoxChecked}"
ContentStringFormat="Is checkbox checked? {0}" />
</StackPanel>
</Grid>
</Window>
C#:
using System.Windows;
namespace StackOverflowTests
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public bool IsCheckBoxChecked
{
get { return (bool)GetValue(IsCheckBoxCheckedProperty); }
set { SetValue(IsCheckBoxCheckedProperty, value); }
}
// Using a DependencyProperty as the backing store for
//IsCheckBoxChecked. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckBoxCheckedProperty =
DependencyProperty.Register("IsCheckBoxChecked", typeof(bool),
typeof(Window1), new UIPropertyMetadata(false));
public Window1()
{
InitializeComponent();
}
}
}
Notice how the only code behind is the Dependency Property. Both the label and the checkbox are bound to it. If the checkbox changes, the label changes too.
Hello this is my first time posting so please be patient:
my answer was to create a simple property:
public bool Checked { get; set; }
Then to set the data context of the Checkbox (called cb1):
cb1.DataContext = this;
Then to bind the IsChecked proerty of it in the xaml
IsChecked="{Binding Checked}"
The code is like this:
XAML
<CheckBox x:Name="cb1"
HorizontalAlignment="Left"
Margin="439,81,0,0"
VerticalAlignment="Top"
Height="35" Width="96"
IsChecked="{Binding Checked}"/>
Code behind
public partial class MainWindow : Window
{
public bool Checked { get; set; }
public MainWindow()
{
InitializeComponent();
cb1.DataContext = this;
}
private void myyButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Checked.ToString());
}
}
Should be easier than that. Just use:
<Checkbox IsChecked="{Binding Path=myVar, UpdateSourceTrigger=PropertyChanged}" />
if you have the property "MyProperty" on your data-class, then you bind the IsChecked like this.... (the converter is optional, but sometimes you need that)
<Window.Resources>
<local:MyBoolConverter x:Key="MyBoolConverterKey"/>
</Window.Resources>
<checkbox IsChecked="{Binding Path=MyProperty, Converter={StaticResource MyBoolConverterKey}}"/>
This works for me (essential code only included, fill more for your needs):
In XAML a user control is defined:
<UserControl x:Class="Mockup.TestTab" ......>
<!-- a checkbox somewhere within the control -->
<!-- IsChecked is bound to Property C1 of the DataContext -->
<CheckBox Content="CheckBox 1" IsChecked="{Binding C1, Mode=TwoWay}" />
</UserControl>
In code behind for UserControl
public partial class TestTab : UserControl
{
public TestTab()
{
InitializeComponent(); // the standard bit
// then we set the DataContex of TestTab Control to a MyViewModel object
// this MyViewModel object becomes the DataContext for all controls
// within TestTab ... including our CheckBox
DataContext = new MyViewModel(....);
}
}
Somewhere in solution class MyViewModel is defined
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool m_c1 = true;
public bool C1 {
get { return m_c1; }
set {
if (m_c1 != value) {
m_c1 = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("C1"));
}
}
}
}
No backend and ViewModel Code:
I made such check box to control other control's visibility.
<CheckBox x:Name="rulerCheckbox" Content="Is Ruler Visible" IsChecked="True"/>
and in the other control, I added such binding:
Visibility="{Binding IsChecked, ElementName=rulerCheckbox, Mode=TwoWay, Converter={StaticResource BoolVisConverter}}">

Categories

Resources