bind the text box of user control through mainwindow text - wpf

I am working on WPF project. I have created a user control name as "CanLogPaneView". this user control contains a Text box called "txt_CanLog".
I have bind this Text box as mentioned below:
<UserControl x:Class="CANCONTROL.CanLogPaneView"
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:CANCONTROL"
xmlns:ViewModels="clr-namespace:CANCONTROL.ViewModels;assembly=CANCONTROL.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="MainWindowViewModel" DataType="{x:Type ViewModels:MainWindowViewModel}">
</DataTemplate>
</UserControl.Resources>
<DockPanel>
**<TextBox x:Name="txt_CanLog" Text="{Binding Text, Source={StaticResource MainWindowViewModel}}" >**
</TextBox>
</DockPanel>
</UserControl>
So I have bind the text box with mainwindow property Text. My main window have a view model. there I defined the property Text as mentioned below:
public string text = string.Empty;
public string Text
{
get
{
return text;
}
set
{
text = text + value;
}
}
in Main window code: MainWindow.xaml.cs I am adding text like
this.ViewModel.Text = "\n\nAPPLICATION CONFIGURATION\r\n";
What I want is through mainwindow.xaml.cs code I want to print some data in CanLogPaneView.xaml's textBox

Your MainWindowViewModel should be binded to your Usercontrol's DataContext instead.
Also, implement INotifyPropertyChanged in your MainWindowViewModel and RaisePropertyChange at your "Text" setter
Something like the following
<Window x:Class="WpfTestProj.MainWindow"
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"
xmlns:local="clr-namespace:WpfTestProj"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=False}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Text}" />
</Grid>
public class MainViewModel : ViewModelBase
{
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged();
}
}
}

Related

WPF reusable label and text box row

In my application I have a form which contains a lot of rows
with the repeated pattern of :
Label and than a Textbox next to it.
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
I am new to wpf but is there a way to create something like a user control which contains these two controls together ?
And each time I just add this new control and modify the Label's content.
Of course there is a way and it is called UserControl. Just right click your project and select Add New Item. Then browse to add a UserControl, here is an example:
<UserControl x:Class="WpfApp.MyUserControl"
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:WpfApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="6*" />
</Grid.ColumnDefinitions>
<Label x:Name="lbl" />
<TextBox Grid.Column="1" Height="20" Width="100" />
</Grid>
</UserControl>
Then for managing the content of the lable you will need a dependency property so that whatever is consuming your user control can bind to it (you can use regular properties too but then binding will not be possible):
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty LabelContentProperty = DependencyProperty.Register(
"LabelContent", typeof(string), typeof(MyUserControl), new PropertyMetadata(default(string),OnLabelContentChanged));
private static void OnLabelContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (MyUserControl) d;
control.lbl.Content = e.NewValue;
}
public string LabelContent
{
get => (string) GetValue(LabelContentProperty);
set => SetValue(LabelContentProperty, value);
}
public MyUserControl()
{
InitializeComponent();
}
}
In case you do not want to use dependency properties then you will be fine with something similar to:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public string LabelContent
{
get => lbl.Content as string;
set => lbl.Content = value;
}
}
And then just use it!
<Window x:Class="WpfApp.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:wpfApp="clr-namespace:WpfApp"
mc:Ignorable="d"
WindowStartupLocation="Manual"
Title="MainWindow">
<Grid>
<wpfApp:MyUserControl LabelContent="Hi there!"/>
</Grid>
</Window>

Change List from MainWindow in WPF

I am trying to change a List that bind to DataGrid from MainWindow (The List is in another class).
How do i do it?
The List contains Tuple with 2 strings and i want to change just the second string when the user enters new values to a textBox in a dialog box (that he open after clicking on a button in the MainWindow.
(At the end i want the user to enter values in this dialog box and then show it in a list in another page (I mean another user control) so im open to hear also about different ways then this list of tuple bind to DataGrid).
How do i change this string from another page (I mean from the MainWindow)?
I tried to use MVVM the problem is that i dont find any connection between the mainWindow and the user control.
Name_List.xaml.cs:
namespace MyApp.Pages.SomeLists
{
public partial class Name_List: UserControl
{
private List<Tuple<string, string>> myNamesList = new List<Tuple<string, string>>();
public Name_List()
{
InitializeComponent();
myNamesList.Add(new Tuple<string, string>("First Name", your_name_bind));
myNamesList.Add(new Tuple<string, string>("Last Name", your_lastName_bind));
NamesGrid.ItemsSource = myNamesList;*/
}
}
}
Name_List.xaml:
<UserControl x:Class="MyApp.Pages.SomeLists.Name_List"
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:MyApp.Pages.SomeLists"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<DataGrid Name="NamesGrid" CanUserReorderColumns="True" CanUserResizeColumns="False" CanUserResizeRows="False" HorizontalAlignment="Left"
GridLinesVisibility="All">
</DataGrid>
</Grid>
</UserControl>
MainWindow.xaml:
<mui:ModernWindow x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
Title="App" IsTitleVisible="True"
Width="1200"
ContentSource="/Pages/Home.xaml">
<mui:ModernWindow.MenuLinkGroups>
<mui:LinkGroup DisplayName="Home page">
<mui:LinkGroup.Links>
<mui:Link DisplayName="home" Source="/Pages/Home.xaml" />
</mui:LinkGroup.Links>
</mui:LinkGroup>
<mui:LinkGroup DisplayName="Lists" >
<mui:LinkGroup.Links>
<mui:Link DisplayName="Open Lists" Source="/Pages/MainLists.xaml" />
</mui:LinkGroup.Links>
</mui:LinkGroup>
<mui:LinkGroup DisplayName="settings" GroupKey="settings">
<mui:LinkGroup.Links>
<mui:Link DisplayName="software" Source="/Pages/SettingsPage.xaml" />
</mui:LinkGroup.Links>
</mui:LinkGroup>
</mui:ModernWindow.MenuLinkGroups>
<mui:ModernWindow.TitleLinks>
<mui:Link x:Name="connect" DisplayName="connect"/>
<mui:Link DisplayName="settings" Source="/Pages/SettingsPage.xaml" />
<mui:Link DisplayName="help" Source="https://github.com" />
</mui:ModernWindow.TitleLinks>
</mui:ModernWindow>
MainWindow.xaml.cs
--There is a long code here... the relevant part is "connect_fun()" function that called after the user click on "OK" in the dialog that opened to him after he clicked on "connect" tab. the dialog contains 2 textBox.--
namespace MyApp
public partial class MainWindow : ModernWindow
{
private string name = "";
private string lastName = "";
//Here i create a Modern dialog in code.
.....
TextBox name_txt = new TextBox();
TextBox lastName_txt = new TextBox();
public MainWindow()
{
InitializeComponent();
}
private void connect_fun(object sender, RoutedEventArgs e)
{
name= name_txt.Text;
lastName = lastName_txt_txt.Text;
}
}
}
MainLists.xaml:
<UserControl x:Class=MyApp.Pages.MainLists"
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:mui="http://firstfloorsoftware.com/ModernUI"
xmlns:local="clr-namespace:MyApp.Pages"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Pages/Styles/BaseButtonStyle2.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
...
</Grid>
<Grid Style="{StaticResource ContentRoot}" Grid.Row="1">
<mui:ModernTab SelectedSource="/Pages/SomeLists/Name_List.xaml" Layout="Tab" >
<mui:ModernTab.Links>
<mui:Link DisplayName="Name List" Source="/Pages/SomeLists/Name_List.xaml"/>
<mui:Link DisplayName="Cars List" Source="/Pages/SomeLists/Cars_List.xaml"/>
</mui:ModernTab.Links>
</mui:ModernTab>
</Grid>
</Grid>
</UserControl>
I want to bind name and lastName to the dataGrid in Name_List.xaml (it means to your_name_bind and your_lastName_bind in myNamesList in my case).

Use base class control in Mainwindow XAML

I wan to create a base class which consits properties of both User contorl and window and that baseclass control used in my Mainwindow.xaml.
Below code i am using but getting following error "Partial declarations of 'MainWindow' must not specify different base classes"
Usercontrol1.xaml
<UserControl x:Class="WpfApplication1.UserControl1"
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:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="80,46,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="80,82,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
</UserControl>
UserControl1.xaml.cs
namespace WpfApplication1
{
public class baseclass : UserControl
{
public Button textBox { get; set; }
public baseclass()
{
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(textBox.ToString()))
{
}
}
}
public partial class UserControl1
{
public UserControl1()
{
InitializeComponent();
}
}
}
Now Problem is that how can i use usecontrol in my Main window.code for main window below
Mainwindow.xaml.cs
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
I'm not sure if I'm missing something obvious or others have missed something obvious! I can add baseclass to MainWindow just fine with:
<Window x:Class="WpfApp2.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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<local:baseclass />
</Window>
The key thing is local: xmlns namespace that's defined as xmlns:local="clr-namespace:WpfApp2"
If you're not merely cargo culting the code, you can see how the above will work for you.
Now the real answer for the question you didn't ask: you're doing this wrong! The textbox in baseclass will never work because you haven't initialised it as a UserControl (there's more to this than just inheriting from UserControl) Learn MvvM and stop relying on code behind. Your life will get much easier.
i want to use base user control in main window this is what i ma trying to do
You can't. A top-level window class cannot inherit from System.Windows.Controls.UserControl. It must inherit from a System.Windows.Window. So it is not possible to define a common base class for both user controls and windows in WPF.
You can change the base class of UserControl1 though but you must specify the same base class in both the XAML markup and the code-behind file:
UserControl1.xaml.cs:
public partial class UserControl1 : baseclass
{
public UserControl1()
{
InitializeComponent();
}
}
UserControl1.xaml:
<local:baseclass x:Class="WpfApplication1.UserControl1"
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:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="80,46,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="80,82,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
</local:baseclass>

How to Expose a Control in XAML

I'm new in WPF and I'm creating a control. This control contains a DataGrid and some other WPF controls.
I created my Control as below:
<UserControl x:Class="MyControls.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="329" d:DesignWidth="535" >
<Grid>
<DataGrid Margin="6,25,6,35" Name="dataGrid" SelectionUnit="CellOrRowHeader" x:FieldModifier="public" HeadersVisibility="All"/>
<OtherControl HorizontalAlignment="Left" x:Name="otherControl" Height="34" VerticalAlignment="Bottom" Width="523" x:FieldModifier="private"/>
<Label Content="caption" Height="24" HorizontalAlignment="Left" Name="captionLabel" VerticalAlignment="Top" Foreground="#FF2626D1" x:FieldModifier="private"/>
</Grid>
</UserControl>
So, everything goes well so far, then I create a container UserControl which has in it my control created previously:
<UserControl x:Class="MyContainers.MyContainer"
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" xmlns:my="clr-namespace:MyControls">
<Grid>
<my:MyControl>
</my:MyControl>
</Grid>
What I can not do is the following:
<my:MyControl>
<my:MyControl.dataGrid>
</my:MyControl.dataGrid>
</my:MyControl>
I previously set the datagrid's property of FieldModifier as public in order to get access to it in another xaml, but it raises an error from visual studio.
I need to "expose" my dataGrid in order to be able to add columns and their styles.
I would like to be able to do something like this:
<my:MyControl.dataGrid.Columns >
<DataGridTextColumn />
<DataGridTextColumn />
...
<DataGridTextColumn />
</my:MyControl.dataGrid.Columns>
So, is not enough to set the datagrid's property of FieldModifier as public?
Do I need to do something else? How can I achieve this? Is this even possible?
I hope someone can help me. Thank you in advance.
You cannot access the child DataGrid as MyControl.dataGrid -- MyControl has no property named "dataGrid".
You might try adding a dependency property of type ObservableCollection<DataGridColumn> to MyControl, and modify the dataGrid columns whenever that collection changes.
EDIT:
Whipped together a quick example for you:
UserControl code:
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(ObservableCollection<DataGridColumn>), typeof(UserControl1));
public ObservableCollection<DataGridColumn> Columns
{
get { return (ObservableCollection<DataGridColumn>)GetValue(ColumnsProperty); }
set { SetValue(ColumnsProperty, value); }
}
public UserControl1()
{
Columns = new ObservableCollection<DataGridColumn>();
Columns.CollectionChanged += (s, a) =>
{
dataGrid.Columns.Clear();
foreach (var column in this.Columns)
dataGrid.Columns.Add(column);
};
InitializeComponent();
}
}
UserControl xaml:
<UserControl x:Class="WpfApplication1.UserControl1"
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">
<Grid>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False"/>
</Grid>
so you can use it like:
<Grid>
<l:UserControl1>
<l:UserControl1.Columns>
<DataGridTextColumn Header="Col1"/>
<DataGridTextColumn Header="Col2"/>
</l:UserControl1.Columns>
</l:UserControl1>
</Grid>

Can not bind View to ViewModel

I'm trying to do a simplest thing: bind a View to ViewModel, but for some reason it doesn't work.
I've got MainWindow:
<Window x:Class="ImagesToAmazon.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:v="clr-namespace:ImagesToAmazon.View"
xmlns:vm="clr-namespace:ImagesToAmazon.ViewModel" >
<Window.Resources>
<DataTemplate DataType="{x:Type vm:MainViewModel}">
<v:MainControl />
</DataTemplate>
</Window.Resources>
<Grid>
</Grid>
MainViewModel:
namespace ImagesToAmazon.ViewModel{
public class MainViewModel {
}}
MainControl:
<UserControl x:Class="ImagesToAmazon.View.MainControl"
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">
<StackPanel>
<Button Content="Button" Height="23" Name="button1" Width="75" />
</StackPanel>
Also, I override App.OnStartup to set MainWindow context:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var window = new MainWindow();
var viewModel = new ViewModel.MainViewModel();
window.DataContext = viewModel;
window.Show();
}
}
All compiles, but I don't see my button from MainControl.
Any clues?
In the main window, replace the Grid with
<ContentControl Content="{Binding }" />
This will attempt to use the current DataContext as the content of the control, and it will use the DataTemplate u defined earlier.

Resources