Binding elements into a DataTemplate in WPF Window - c#

I have five definitions of DataTemplate in my window, according with a CantidadLlantas property, I choose one of these to show it. Until here all works fine.
But, in each DataTemplate there are some TextBox with Text property binding to one property in my ViewModel, and this isn't working, if I show these same properties in TextBoxes out of the DataTemplates the values shown are ok, is like if the binding not is binding into the DataTemplates... Why?
One of the templates the more simple is the next:
<Window.Resources>
<DataTemplate x:Name="Llantas2Template" x:Key="Llantas2Template" DataType="ContentControl">
<Grid Name="grdLlantas">
<Border Name="borLlantas" BorderBrush="Black" BorderThickness="1" Margin="0,0,0,0" Background="DarkSeaGreen" />
<Rectangle Fill="Yellow" HorizontalAlignment="Left" Height="30" Stroke="Black" VerticalAlignment="Top" Width="5" Margin="0,16,0,0" />
<Rectangle Fill="Yellow" HorizontalAlignment="Left" Height="30" Stroke="Black" VerticalAlignment="Top" Width="5" Margin="0,130,0,0" />
<Rectangle HorizontalAlignment="Left" Height="175" Stroke="Black" StrokeThickness="3" VerticalAlignment="Top" Width="70" Margin="20,10,10,10" />
<Line X1="230" Y1="10" X2="230" Y2="150" Stroke="Black" StrokeThickness="3" />
<Ellipse Fill="Black" Height="25" Width="10" StrokeThickness="2" Stroke="Black" Margin="180,0,0,10"/>
<TextBox Name="txtLlanta2" Margin="200,10,20,20" ToolTipService.ToolTip="Llanta trasera derecha"
Width="60" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Llanta2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Name="txtLlanta1" Margin="200,150,20,10" ToolTipService.ToolTip="Llanta trasera izquierda"
Width="60" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Llanta1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
Then in the window I declare a ContentControl into a StackPanel the visibility of which depends of a property in my ViewModel, this works fine:
<StackPanel Name="stkLlantas" Grid.Row="2" Visibility="{Binding IsVisibilityTemplate}" >
<!--Aquí se pondrá el UserControl con el Template de Llantas que corresponde-->
<ContentControl Grid.Row="2" Name="LlantasContent"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Margin="0,10,0,10" />
</StackPanel>
the selection of the template is in behind:
#region DefineTemplate
private void DefineTemplate()
{
switch (cantidadLlantas)
{
case 2:
LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas2Template");
break;
case 4:
LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas4Template");
break;
case 6:
LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas6Template");
break;
case 8:
LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas8Template");
break;
case 10:
LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas10Template");
break;
default:
LlantasContent.ContentTemplate = null;
break;
}
}
#endregion
In behind I define the DataContext for my window:
UnidadLlantasVM viewModel;
int cantidadLlantas;
public wUnidadLlantas(string _IDUni, int _CantidadLlantas)
{
this.Loaded += (s, a) =>
{
cantidadLlantas = _CantidadLlantas;
viewModel = new UnidadLlantasVM();
viewModel.IDUni = _IDUni;
viewModel.CantidadLlantas = _CantidadLlantas;
this.DataContext = viewModel;
DefineTemplate();
};
InitializeComponent();
}
And in xaml:
<Window x:Class="MTTO.wUnidadLlantas"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
With test purposes, I add TextBoxes in the window, with the same properties that should be showed into the template and here works fine, anex the image:
all the data sowed in the window are properties of my ViewModel and works fine, but into the template not, the TextBoxes in the picture down should be the same that the TextBoxes pointed in red. What happen? I have a Silverlight project with the same, and there works fine...

Probably you need to bind the DataContext to the ContentControl's Content property (which to me has a little smell of a design flaw in WPF, but never mind).
<StackPanel Name="stkLlantas" Grid.Row="2" Visibility="{Binding IsVisibilityTemplate}" >
<!--Aquí se pondrá el UserControl con el Template de Llantas que corresponde-->
<ContentControl Grid.Row="2" Name="LlantasContent"
Content="{Binding}"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Margin="0,10,0,10" />
</StackPanel
By the way, consider using a ContentTemplateSelector, for the thing you do in DefineTemplate. This is the default API for template selection.
You would move your existing code and logic from Define Template to SelectTemplate.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.contentcontrol.contenttemplateselector?view=windowsdesktop-6.0
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.datatemplateselector.selecttemplate?view=windowsdesktop-6.0

Related

C# wpf caliburn.Micro MahApps HamburgerMenu.ContentTemplate data binding is not working

I'm making an application using Caliburn.Micro(for easy data binding and stuff) and MahApps.Metro(for designing).
I've created a View name 'MainView' which has HamburgerMenu of MahApps.
My issue is data binding is working fine under HamburgerMenu.ContentTemplate tag
Here is my HamburgerMenu.ContentTemplate xaml.
<Page x:Class="Sample.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:utils="clr-namespace:Omni.WindowsClient.Utils"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Omni.WindowsClient.Views"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="600">
<Page.Resources>
<DataTemplate x:Key="HamburgerMenuItem"
DataType="{x:Type mah:HamburgerMenuItem}">
<Grid Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Margin="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="{Binding Glyph}"
Stretch="UniformToFill" />
<TextBlock Grid.Column="1"
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Label}" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<mah:HamburgerMenu x:Name="HamburgerMenuControl"
SelectedIndex="0"
ItemTemplate="{StaticResource HamburgerMenuItem}"
OptionsItemTemplate="{StaticResource HamburgerMenuItem}"
IsPaneOpen="True"
DisplayMode="CompactInline"
cal:Message.Attach="[Event ItemClick] = [Action ShowDetails(HamburgerMenuControl.SelectedItem)]"
DataContext="{Binding RelativeSource={RelativeSource self}}">
<mah:HamburgerMenu.ItemsSource>
<mah:HamburgerMenuItemCollection>
<mah:HamburgerMenuItem Label="System Status">
<mah:HamburgerMenuItem.Tag>
<iconPacks:PackIconFontAwesome Width="22"
Height="22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Kind="Tasks" />
</mah:HamburgerMenuItem.Tag>
</mah:HamburgerMenuItem>
<mah:HamburgerMenuItem Label="Inbox">
<mah:HamburgerMenuItem.Tag>
<iconPacks:PackIconFontAwesome Width="22"
Height="22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Kind="Inbox" />
</mah:HamburgerMenuItem.Tag>
</mah:HamburgerMenuItem>
<mah:HamburgerMenuItem.Tag>
<iconPacks:PackIconFontAwesome Width="22"
Height="22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Kind="Certificate" />
</mah:HamburgerMenuItem.Tag>
</mah:HamburgerMenuItem>
</mah:HamburgerMenuItemCollection>
</mah:HamburgerMenu.ItemsSource>
<mah:HamburgerMenu.ContentTemplate>
<DataTemplate DataType="{x:Type mah:HamburgerMenuItem}">
<Grid utils:GridUtils.RowDefinitions="48,*">
<!--cal:Action.TargetWithoutContext="{Binding ElementName=HamburgerMenuControl, Path=DataContext}"-->
<Border Grid.Row="0"
Background="{DynamicResource MahApps.Metro.HamburgerMenu.PaneBackgroundBrush}">
<TextBlock x:Name="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="24"
Foreground="White" />
<!--Text="{Binding Path=Header, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"-->
</Border>
<Frame Grid.Row="1"
cal:Message.Attach="RegisterFrame($source)"
DataContext="{x:Null}"
NavigationUIVisibility="Hidden" />
</Grid>
</DataTemplate>
</mah:HamburgerMenu.ContentTemplate>
</mah:HamburgerMenu>
</Grid>
</Page>
and respective view model code is:
using Caliburn.Micro;
using MahApps.Metro.Controls;
using System.Windows.Controls;
namespace Sample.ViewModels
{
public class MainViewModel : Screen
{
private readonly SimpleContainer _container;
private INavigationService _navigationService;
private string _header;
public string HeaderTitle
{
get { return _header; }
set
{
_header = value;
NotifyOfPropertyChange();
}
}
public MainViewModel(SimpleContainer container)
{
this._container = container;
DisplayName = "Main";
}
public void RegisterFrame(Frame frame)
{
_navigationService = new FrameAdapter(frame);
_container.Instance(_navigationService);
_navigationService.NavigateToViewModel(typeof(SystemStatusViewModel));
HeaderTitle = "System Status";
}
public void ShowDetails(HamburgerMenuItem menuItem)
{
switch (menuItem.Label)
{
case "System Status":
_navigationService.NavigateToViewModel(typeof(SystemStatusViewModel));
HeaderTitle = "System Status";
break;
case "Inbox":
_navigationService.NavigateToViewModel(typeof(InboxViewModel));
HeaderTitle = "Inbox";
break;
default:
break;
}
}
}
}
I want to change View in frame under HamburgerMenu.ContentTemplate when I click on menu item.
Like System Status view is SystemStatusView
and Inbox view is InboxView.
My code is working fine (it changes the view in frame and change the Header label too) if I don't use HamburgerMenu.ContentTemplate. But I want to use HamburgerMenu.ContentTemplate to work with HamburgerMenu.
Thanks!
If it's working fine if you don't use HamburgerMenu.ContentTemplate, but stops working when you do, the problem is probably with you overwriting the default template in a way that doesn't support all functionalities of a control.
I'd suggest you to use Blend to get the default HamburgerMenu.ContentTemplate, then just edit it to your needs, without changing too much (keep in mind that names of controls used as a template may have a crucial meaning, so be careful what you are editing).
If you don't know how to use Blend to get your control's template, here is a simple tutorial described in a documentation of Telerik controls (don't worry, it works the same for all controls). You just need to create copy of a HamburgerMenu.ContentTemplate, paste it to your application and you are good to go (editing).

WPF - Change Controls based on listviewitem selection. Controls not updating

I'm trying to update the controls present on my Main Window based on the listviewitem selected by the user, but when the listviewitem selection is changed the controls do not update.
I used this post as reference How to dynamically change a WPF control's template using a checkbox?
EDIT: I initially used ContentTemplate but changed this to DataTemplate based on suggestions, however it still is not updating
The XMAL for my Main Window is
<Window.Resources>
<DataTemplate x:Key="Default">
<Grid Margin="20,280,0,0" />
</DataTemplate>
<DataTemplate x:Key="ERAFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select File" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtEraFileName" HorizontalAlignment="Left" Height="23" Margin="10,80,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="235"/>
<Button x:Name="btnSelectFiles" Content="Manually Select File(s)" HorizontalAlignment="Left" Margin="10,161,0,0" VerticalAlignment="Top" Width="235" Height="45"/>
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="FCSFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select Files" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtFCSFileName_TQ02" HorizontalAlignment="Left" Height="23" Margin="10,40,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ02" Content="Select" HorizontalAlignment="Left" Margin="189,37,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ11" HorizontalAlignment="Left" Height="23" Margin="10,105,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ11" Content="Selec" HorizontalAlignment="Left" Margin="189,100,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ16" HorizontalAlignment="Left" Height="23" Margin="10,170,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ16" Content="Select" HorizontalAlignment="Left" Margin="189,165,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid Margin="0,0,2,0">
<GroupBox x:Name="gbxProgress" Header="Progress" HorizontalAlignment="Left" Margin="298,105,0,0" VerticalAlignment="Top" Height="445" Width="462" Foreground="Black">
<ListBox x:Name="lbxProgress" HorizontalAlignment="Left" Height="408" Margin="10,10,0,0" VerticalAlignment="Top" Width="431" Foreground="Black" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Progress.Message}" />
</GroupBox>
<Button x:Name="btnStart" Content="Start" HorizontalAlignment="Left" Margin="20,513,0,0" VerticalAlignment="Top" Width="100" Height="37" IsEnabled="{Binding Properties.StartButtonEnabled}" Click="btnStart_Click"/>
<Button x:Name="btnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="177,513,0,0" VerticalAlignment="Top" Width="100" Height="37"/>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="70" Margin="20,21,0,0" VerticalAlignment="Top" Width="740" CornerRadius="15">
<Grid>
<Image HorizontalAlignment ="Left" Margin="10" Height="50" Width="50" VerticalAlignment="Center" Source="/Lib/Icons/User.png" />
<TextBlock Name="txtUser" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="78,19,0,19"/>
<Image HorizontalAlignment ="Left" Margin="443,8,0,10" Height="50" Width="50" VerticalAlignment="Center" Source="Lib/Icons/Watch.png" />
<TextBlock x:Name="txtRunTime" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="519,19,0,19" Text="{Binding AppRunTime.TimeElapsed}" />
</Grid>
</Border>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="144" Margin="20,119,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid>
<Label x:Name="lblProcessSelection" Content="Process Selection" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<ListView x:Name="lvProcessSelection" HorizontalAlignment="Left" Height="93" Margin="10,30,0,0" VerticalAlignment="Top" Width="235" BorderThickness="0" SelectionChanged="lvProcessSelection_SelectionChanged">
<ListViewItem Name="itmERA" Content="Expense Reserve Automation"/>
<ListViewItem Name="itmFCS" Content="Financial Close Status"/>
<ListViewItem Name="itmPEL" Content="Peel"/>
</ListView>
</Grid>
</Border>
<ContentControl DataContext="{Binding Properties}" Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Expense Reserve Automation">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Financial Close Status">
<Setter Property="ContentTemplate" Value="{StaticResource FCSFileSelect}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
ViewModel Code is
public class MainWindowModel
{
public ApplicationRunTime AppRunTime { get; set; }
public LogMessage Progress { get; set; }
public MainWindowProperties Properties { get; set; }
public MainWindowModel()
{
AppRunTime = new ApplicationRunTime();
Progress = new LogMessage();
Properties = new MainWindowProperties();
Properties.StartButtonEnabled = false;
}
}
With the MainWindowProperties class
public class MainWindowProperties
{
public bool StartButtonEnabled { get; set; }
public string SelectedProcess { get; set; }
}
And within my MainWindow Constructor I have set the DataContext
mainWindowModel = new MainWindowModel();
this.DataContext = mainWindowModel;
When the selection from lvProcessSelection is changed the following code is executed
if (lvProcessSelection.SelectedItems.Count > 0)
{
mainWindowModel.Properties.SelectedProcess = ((ListViewItem)lvProcessSelection.SelectedItem).Content.ToString();
}
else
{
mainWindowModel.Properties.SelectedProcess = string.Empty;
}
This will update SelectedProcess within my ViewModel with either "Expense Reserve Automation" or "Financial Close Status"
I know the DataContext is set correctly for my ViewModel (but may not be for the ContentControl) as I am able to update lbxProgress with new messages and update txtRunTime with the application RunTime
However when I change the selection on lvProcessSelection nothing happens; the default controls of ERAFileSelect remains.
Could anybody point me in the right direction on how to solve this?
Could anybody point me in the right direction on how to solve this?
Your MainWindowProperties class should implement the INotifyPropertyChanged interface and raise change notifications whenever the SelectedProcess property is set to a new value:
public class MainWindowProperties : INotifyPropertyChanged
{
public bool StartButtonEnabled { get; set; }
private string _selectedProcess;
public string SelectedProcess
{
get { return _selectedProcess; }
set { _selectedProcess = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Please refer to MSDN for more information about this common interface: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
Every view model/model that you bind to must implement this interface and raise change notifications for any target value in the view to be updated.
Why you are not using Data template? Data template will work in this scenario.

How to create databinding in code behind using the same object that is initiated in xaml?

I have the following code :
<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" xmlns:oxy="http://oxyplot.org/wpf"
xmlns:vm="clr-namespace:ViewModel;assembly=ViewModel"
Background="#FFDEDEDE"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d"
Title="Compression Test" Height="1080" Width="1920">
<Window.Resources>
<vm:MainViewModel x:Key="vmMain"
sampleCount="100" />
</Window.Resources>
<Grid x:Name="gridUI">
<StackPanel Orientation="Vertical">
<StackPanel Height="100">
<Border Background="#FF8986D3" Height="100" Margin="0,0,0,30" >
<TextBlock Text="COMPRESSION TEST" FontFamily="Sans-serif" FontSize="30" Foreground="#FFF9F9F9" VerticalAlignment="Center" FontWeight="Medium" HorizontalAlignment="Center"/>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="auto">
<Border BorderBrush="White" BorderThickness="2" >
<StackPanel Orientation="Vertical" Width="200" Height="1080">
<Label FontSize="24" FontFamily="Sans-serif" FontWeight="Medium" Name="doc" Foreground="White" Background="#FFA39AD8" Width="200" HorizontalContentAlignment="Center" Height="43">Files</Label>
<Border BorderBrush="#FFD4D4D4" BorderThickness="0.5" Grid.Row="3"></Border>
<StackPanel Name="sp_doc" Margin="0,10,0,0" >
<StackPanel Orientation="Horizontal" Name="sp_sample_button" Grid.Row="0" Grid.Column="0">
<Image Source="pack://application:,,,/Resources/413.png" Height="40" Width="40" UseLayoutRounding="True" MouseDown="sampleDropDown" Cursor="Hand" Margin="5,0,0,0" Name="up_arrow"/>
<Image Source="pack://application:,,,/Resources/412.png" Height="40" Width="40" UseLayoutRounding="True" MouseDown="sampleDropDown" Cursor="Hand" Margin="5,0,0,0" Name="down_arrow" Visibility="Collapsed"/>
<!--<Button x:Name="sss" Click="sampleDropDown">s</Button>-->
<Label FontSize="18" FontFamily="Sans-serif" FontWeight="Light" Name="sam" Foreground="White" Margin="10">Samples</Label>
</StackPanel>
<StackPanel Orientation="Vertical" Name="sp_s">
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="1">
<Image Source="pack://application:,,,/Resources/413.png" Height="40" Width="40" UseLayoutRounding="True" RenderTransformOrigin="-0.,0.558" MouseDown="reportDropDown" Cursor="Hand" Margin="5,0,0,0" Name="up_arrow1"/>
<Image Source="pack://application:,,,/Resources/412.png" Height="40" Width="40" UseLayoutRounding="True" Cursor="Hand" Margin="5,0,0,0" Name="down_arrow1" Visibility="Collapsed" MouseDown="reportDropDown"/>
<!--<Button Click="reportDropDown">r</Button>-->
<Label FontFamily="Sans-serif" FontWeight="Light" Foreground="White" FontSize="18" Margin="10">Reports</Label>
</StackPanel>
<StackPanel Orientation="Vertical" Name="sp_r">
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Width="1781">
<StackPanel Orientation="Horizontal" Background="#FFFDFDFD" Height="111">
<TextBox Name="sampleCount" Text="{Binding sampleCount, Source={StaticResource vmMain}, UpdateSourceTrigger=PropertyChanged}" Width="200"></TextBox>
<Button Cursor="Hand" Height="75" Width="75" Style="{StaticResource CircleButton}" FontFamily="Sans-Serif" FontSize="25" Foreground="White" Click="NewSample_Click" Content="+" Margin="20,0,0,0" Background="#FFACAABF" />
<StackPanel Margin="20,19,0,0">
<Image Source="pack://application:,,,/Resources/file512.png" Height="75" Width="75" UseLayoutRounding="True" Margin="0,0,0,0" MouseDown="CreateReport_Click" Cursor="Hand" SnapsToDevicePixels="True"/>
</StackPanel>
<Image Source="pack://application:,,,/Resources/play1.png" Height="75" Width="75" UseLayoutRounding="True" Margin="20,18,0,18" MouseDown="CreateReport_Click" Cursor="Hand" SnapsToDevicePixels="True"/>
<Image Source="pack://application:,,,/Resources/1131.png" Height="75" Width="75" UseLayoutRounding="True" Margin="1340,0,0,0" MouseDown="CreateReport_Click" Cursor="Hand"/>
</StackPanel>
<Frame x:Name="newSampleFrame" Content="" HorizontalAlignment="center" VerticalAlignment="center" Width="934" Height="456" NavigationUIVisibility="Hidden" RenderTransformOrigin="0.408,0.5" Visibility="Collapsed"/>
<Frame x:Name="reportFrame" Content="" HorizontalAlignment="Center" Height="842" VerticalAlignment="Center" Width="595" Margin="0,100,0,0" NavigationUIVisibility="Hidden"/>
<Frame x:Name="graphFrame" Content="" HorizontalAlignment="Center" Height="456" VerticalAlignment="Center" Width="934" NavigationUIVisibility="Hidden" Visibility="Collapsed"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Window>
MainViewModel.cs :
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewModel
{
public class MainViewModel : ObservableObject
{
public MainViewModel()
{
}
private string[] sampleName;
private string _sampleCount;
public Data obj2 = new Data();
public string this[int pos]
{
get
{
return sampleName[pos];
}
set
{
sampleName[pos] = value;
}
}
public string sampleCount
{
get
{
return _sampleCount;
}
set
{
if (value != _sampleCount)
{
_sampleCount = value;
OnPropertyChanged("sampleCount");
Console.WriteLine("Test");
Console.WriteLine(value);
obj2.sampleCount = value;
SaveFile.saveFileMain(obj2);
}
}
}
}
}
And I have the following code that create a textblock whenever I click on the OK button :
window2.xaml.cs:
private void Ok_Click(object sender, MouseButtonEventArgs e)
{
MainWindow win = (MainWindow)Application.Current.MainWindow;
int i = 1; // counter for the name of each new textblock
string name = String.Concat("sample", i);
// add textblok to the document list of new samples
if (File_name.Text != "")
{
TextBlock sampleText = new TextBlock();
sampleText.Text = File_name.Text;
sampleText.FontSize = 14;
sampleText.FontFamily = new FontFamily("Sans-serif");
sampleText.FontWeight = FontWeights.DemiBold;
sampleText.Margin = new Thickness(20,0,0,0);
sampleText.Name = name;
sampleText.PreviewMouseDown += new MouseButtonEventHandler(test1);
sampleText.Visibility = System.Windows.Visibility.Collapsed;
//binding
Binding myBinding = new Binding();
myBinding.Source =
myBinding.Path = new PropertyPath("sampleName");
myBinding.Mode = BindingMode.TwoWay;
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
sampleText.SetBinding(TextBlock.TextProperty, myBinding);
Grid.SetColumn(sampleText, 0);
win.sp_s.Children.Add(sampleText);
// checking if the drop down of sample is already open, if so it will show the last textblock with pressing the arrow button.
var textblockSample = win.sp_s.Children.OfType<TextBlock>().FirstOrDefault();
if (textblockSample.Visibility == System.Windows.Visibility.Visible)
{
sampleText.Visibility = System.Windows.Visibility.Visible;
}
}
i += 1; // increasing the loop of names by 1
this.Close();
}
Is it possible to use the same object that is initiated in xaml (vmMain) as a source for binding the textblock (sample text) to sampleName property?
Not sure why you don't set DataContext of your MainWindow to MainViewModel.
<Window.DataContext>
<StaticResourceExtension ResourceKey="vmMain" />
</Window.DataContext>
Or, you can even set DataContext via MainWindow's code behind, which you don't seem to intent to not keep it untouched.
Then to set binding source:
myBinding.Source = this.DataContext;
In the case you refused to set the DataContext, you still can:
myBinding.Source = this.FindResource("vmMain") as MainViewModel;
Not sure if I managed to solve your problem.
Edit
I just realised your binding is in window2. You should do this:
myBinding.Source = win.DataContext;
Similarly, myBinding.Source = this.FindResource("vmMain") as MainViewModel; should also be changed to myBinding.Source = win.FindResource("vmMain") as MainViewModel;.
This is provided you still have that MainWindow win = (MainWindow)Application.Current.MainWindow; line there.
I believe that what you are looking for is the resources property:
myBinding.Source = Resources["vmMain"];
Resource allows you to access the XAML-defined (or otherwise) resources for the current object - the window.
You can also access the resources of any FrameworkElement in the same manner.
EDIT: I hadn't noted the fact that the vmMain was in a different class. With this in mind, no there is no way to reference that object directly from Window2 as there may be multiple MainWindows so you'd have to pick which MainWindow instance the vmMain should be taken from.
What you can do, however is create vmMain in your Application object (App.xaml). This would then share that object across all FrameworkElements in your application. To access this you could use
myBinding.Source = Application.Currennt.Resources["vmMain"];

Data Will Not Bind WP

Im trying to bind data from a XML file, ive followed tuts from mdsn and other online sources but i keep getting an error, if i bind the data to a listbox it works fine.
public void LoadPage()
{
XDocument loadedData = XDocument.Load("page01.xml");
var data = from query in loadedData.Descendants("page")
select new PageReader
{
PageNumber = (int)query.Element("pnumber"),
ChapterTitle = (string)query.Element("ctitle"),
ChapterNumber = (int)query.Element("cnumber")
};
LayoutRoot.DataContext = data;
}
and the XAML
Grid x:Name="LayoutRoot" Background="#FFFFFEFE">
<StackPanel>
<Grid>
<Rectangle Fill="#FF424242" HorizontalAlignment="Left" Height="60" Stroke="Black" VerticalAlignment="Top" Width="480"/>
<StackPanel Orientation="Horizontal">
<TextBlock Width="100" TextWrapping="Wrap" MaxWidth="100" MaxHeight="58" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFB6AEAE" FontFamily="{StaticResource lob2}" Text="{Binding ChapterNumber}"/>
<TextBlock Width="280" TextWrapping="Wrap" MaxWidth="300" MaxHeight="58" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFB6AEAE" FontFamily="{StaticResource lob2}" Text="{Binding ChapterTitle}"/>
<TextBlock Width="100" TextWrapping="Wrap" MaxWidth="100" MaxHeight="58" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFB6AEAE" FontFamily="{StaticResource lob2}" Text="{Binding PageNumber}"/>
</StackPanel>
</Grid>
<Grid Height="30"></Grid>
<TextBlock x:Name="PageText" Height="640" ScrollViewer.VerticalScrollBarVisibility="Visible"></TextBlock>
</StackPanel>
</Grid>
Your data is of type IEnumerable<PageReader>, which is why it would work with a ListBox as ListBox is expecting a collection.
If you change
LayoutRoot.DataContext = data;
to
LayoutRoot.DataContext = data.FirstOrDefault();
At least you should see some data show up on the UI.

WPF Bool DataTrigger - Change Font Colour

I want to change the font colour of a number of items on a WPF page based on the theme selected by the user. (there is a light theme, and a dark theme)
I'm using a datatemplate to customise the content of a listbox, when the theme is Dark, I want to change all the textblock font colours to White.
My the class behind the page I'm setting 'DarkTheme' to true.
I've successfully set triggers below, however I can't figure out how to do this from a value set on the pages class.
So, how can I style the font colour of the textblocks to white if DarkTheme = true?
Code:
public partial class Media : UserControl
{
public bool DarkTheme { get; set; }
readonly DatabaseAsset _dbAssets = new DatabaseAsset();
public Media()
{
InitializeComponent();
RefreshMediaList();
DarkTheme = Global.Configuration.IsDarkModeAppliedAsTheme();
}
}
XAML:
<UserControl.Resources>
<db:MediaAsset x:Key="MediaAsset"/>
<DataTemplate x:Key="MediaAssetItemTemplate">
<ListBoxItem Height="70" Name="ListBoxItem">
<DockPanel Margin="0,0,0,0" Height="65">
<DockPanel DockPanel.Dock="Left" Name="VideoImage2" Height="65" Width="102">
<Button Name="ListBoxItemSelect" Click="ButtonBase_OnClick" Tag="{Binding Path=Id}">
<Path Name="test" Width="38" Height="30.0833" Canvas.Left="19" Canvas.Top="22.1667" Stretch="Fill" Fill="#FF000000" Data="F1 M 19,34.8333L 22.1667,34.8333L 22.1667,42.75L 19,42.75L 19,34.8333 Z M 22.9583,34.0417L 49.4791,34.0417L 49.4791,38L 50.6667,38L 57,31.6667L 57,52.25L 50.6667,45.9167L 49.4791,45.9167L 49.4791,52.25L 22.9583,52.25L 22.9583,34.0417 Z M 29.2917,22.1667C 32.3522,22.1667 34.8333,24.6478 34.8333,27.7083C 34.8333,30.7689 32.3522,33.25 29.2917,33.25C 26.2311,33.25 23.75,30.7689 23.75,27.7083C 23.75,24.6478 26.2311,22.1667 29.2917,22.1667 Z M 41.9583,22.1667C 45.0189,22.1667 47.5,24.6478 47.5,27.7083C 47.5,30.7689 45.0189,33.25 41.9583,33.25C 38.8977,33.25 36.4167,30.7689 36.4167,27.7083C 36.4167,24.6478 38.8977,22.1667 41.9583,22.1667 Z "/>
</Button>
</DockPanel>
<DockPanel Dock="Left" Name="VideoData2" HorizontalAlignment="Stretch" Height="65">
<TextBlock DockPanel.Dock="Top" Text="{Binding Path=Title}" FontWeight="Bold" FontSize="18"></TextBlock>
<TextBlock DockPanel.Dock="Top" TextTrimming="CharacterEllipsis" Text="{Binding Path=Description}" TextWrapping="NoWrap" FontSize="13" Margin="0,0,0,0"/>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=VideoCatNane}" FontSize="12" FontStyle="Italic"/>
<Border Width="50"></Border>
<TextBlock Text="{Binding Path=MediaState}" FontSize="12"/>
</StackPanel>
</DockPanel>
</DockPanel>
</ListBoxItem>
</DataTemplate>
</UserControl.Resources>
That's not the right way to do theming in WPF.
But if you want a quick solution, Move the InitializeComponent() statement to the bottom of your constructor:
public Media()
{
RefreshMediaList();
DarkTheme = Global.Configuration.IsDarkModeAppliedAsTheme();
InitializeComponent(); // <-- Here
}

Categories