What is the purpose of Application.Resources if my windows cannot access the resources defined within it?
This works, I get a window with a TextBox that says "Loki" inside of it...
App.xaml.cs:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ViewModel.ViewModel1 oVM = new ViewModel.ViewModel1 { Name = "Loki" };
MainWindow oVW = new MainWindow { Content = oVM };
oVW.ShowDialog();
}
}
MainWindow.xaml
<Window x:Class="TableGenerator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TableGenerator.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:ViewModel1}">
<TextBox Text="{Binding Path=Name}" />
</DataTemplate>
</Window.Resources>
<ContentPresenter />
</Window>
But moving the DataTemplate to Application.Resources instead of Window.Resources does not work. When I run this I get a window, there is no TextBox at all, but there is text being displayed somehow that just says the name of my viewmodel class, "TableGenerator.ViewModel.ViewModel1".
App.xaml.cs is unchanged.
MainWindow.xaml changes to:
<Window x:Class="TableGenerator.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">
<ContentPresenter />
</Window>
App.xaml:
<Application x:Class="TableGenerator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TableGenerator.ViewModel">
<Application.Resources>
<DataTemplate DataType="{x:Type vm:ViewModel1}">
<TextBox Text="{Binding Path=Name}" />
</DataTemplate>
</Application.Resources>
</Application>
Why does it not look in Application.Resources to find my DataTemplate?
Add your datatemplate to a dictionary. It is required to have a default style which application resources should have it seems. Refer link for more explaination. datatemplate in app.xaml is not getting picked up without any styles?
On the creation of every object in XAML, if a default style is present (i.e. style w/ a key of Type) that style should be applied. As you can imagine there are several performance optimizations to make that (implied) lookup a light weight as possible.
One of them is that we don’t look inside Resource Dictionaries unless they are flagged as “containing default Styles”. There is a bug: if all your default styles are nested in merged dictionaries three levels deep (or deeper) the top dictionary does not get flagged so the search skips it. The work around is to put a default Style to something, anything, in the root Dictionary.
Then refer the below code.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SQ15Mar2015_Learning">
<DataTemplate DataType="{x:Type vm:ViewModel}">
<DockPanel>
<TextBox Text="{Binding Path=Name,UpdateSourceTrigger=PropertyChanged}">
</TextBox>
</DockPanel>
</DataTemplate>
<Application x:Class="SQ15Mar2015_Learning.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SQ15Mar2015_Learning">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
OR
<Application.Resources>
<DataTemplate DataType="{x:Type vm:ViewModel}">
<DockPanel>
<TextBox Text="{Binding Path=Name,UpdateSourceTrigger=PropertyChanged}">
</TextBox>
</DockPanel>
</DataTemplate>
<Style TargetType="{x:Type Rectangle}" />
</Application.Resources>
class ViewModel : INotifyPropertyChanged
{
private string myVar;
public string Name
{
get { return myVar; }
set
{
if (value != myVar)
{
myVar = value;
OnPropertyChanged("Name");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ViewModel oVM = new ViewModel { Name = "Loki" };
MainWindow oVW = new MainWindow();
oVW.DataContext = oVM;
oVW.ShowDialog();
}
}
<Window x:Class="SQ15Mar2015_Learning.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SQ15Mar2015_Learning"
Title="MainWindow" Height="350" Width="525" >
<Grid>
<ContentControl Content="{Binding }" />
</Grid>
</Window>
Related
Using Xceed DataGrid for WPF
How can you use generated sample data source (generated in Expression Blend) as the source for DataGridCollectionViewSource? Is it possible?
<xcdg:DataGridCollectionViewSource x:Key="cvsSample"
Source="{Binding Source={x:Static Application.Current},Path=SampleDataSource}"/>
Doing this throw an error:
A value of type 'DataGridCollectionViewSource' cannot be added to a collection or dictionary of type 'UIElementCollection'.
I can set it directly in the DataGridControl like so:
<xcdg:DataGridControl ItemTemplate="{DynamicResource ItemTemplate}"
ItemsSource="{Binding Collection, Source={StaticResource SampleDataSource}}"
UpdateSourceTrigger="CellContentChanged"
Margin="10">
</xcdg:DataGridControl>
But I want to use the DataGridCollectionViewSource as it allows you to use the filtering, grouping etc. functionality.
Try this:
XAML:
<Window x:Class="WpfApp1.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:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvsSample" Source="{Binding}" />
</Window.Resources>
<Grid>
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource cvsSample}}"/>
</Grid>
</Window>
CS:
using Xceed.Wpf.Samples.SampleData;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = SampleDataProvider.GetProducts();
}
}
Look at jstreet's answer, but if that doesnt work for you, you can try doing what I did.
In Visual Studio go to Project > Add Reference > Extensions and add Xceed.Wpf.DataGrid.Samples.SampleData (remember to check the little box next to it).
App.xaml.cs
public partial class App : System.Windows.Application
{
protected override void OnStartup(StartupEventArgs e)
{
Xceed.Wpf.DataGrid.Licenser.LicenseKey = "XXXXX-XXXXX-XXXXX-XXXX";
DataSet musicDataSet = Xceed.Wpf.DataGrid.Samples.SampleData.DataProvider.GetMusicLibraryDataSet();
m_songs = musicDataSet.Tables["Songs"];
base.OnStartup(e);
}
private DataTable m_songs;
public DataTable Songs
{
get
{
return m_songs;
}
}
}
MainWindow.xaml
<Window.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvsSongs"
Source="{Binding Source={x:Static Application.Current},Path=Songs}">
</xcdg:DataGridCollectionViewSource>
</Window.Resources>
<Grid>
<xcdg:DataGridControl ItemsSource="{Binding Source={StaticResource cvsSongs}}"/>
</Grid>
Can't believe I struggled this much just to have missed a reference...
private void Button_Click(object sender, RoutedEventArgs e)
{
int selectedValue = (int)comboSelection.SelectedValue;
if (selectedValue == 8)
{
EightTiles et = new EightTiles();
this.Visibility = Visibility.Collapsed;
et.Visibility = Visibility.Visible;
}
}
My target is when the combo box selection is equal to 8 then click the button, current usercontrol get collapsed and next usercontrol(EightTiles) get visible.
But my problem is when i click the button it shows a blank page, next user control page doesn't showed, what is the problem and how i do to solve it..
Thanks
Plase both these controls as content of a main content control to xaml, and manage the second control visibility based on trigger of the first control. Here what I can suggest you:
1. XAML:
<Window x:Class="SoDataGridProjectsHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:soDataGridProjectsHelpAttempt="clr-namespace:SoDataGridProjectsHelpAttempt"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl >
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid>
<soDataGridProjectsHelpAttempt:MainSubControl x:Name="MainSubControl" Visibility="Visible"/>
<soDataGridProjectsHelpAttempt:SubSubControl x:Name="SubSubControl" Visibility="Collapsed"/>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="Control.Visibility" Value="Collapsed" SourceName="MainSubControl">
<Setter TargetName="SubSubControl" Property="Visibility" Value="Visible"></Setter>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Grid>
2. MainSubControl:
<UserControl x:Class="SoDataGridProjectsHelpAttempt.MainSubControl"
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:soDataGridProjectsHelpAttempt="clr-namespace:SoDataGridProjectsHelpAttempt"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Visibility="{Binding IsControlVisible, Converter={StaticResource Bol2VisibilityConverter}, UpdateSourceTrigger=PropertyChanged}">
<UserControl.Resources>
<x:Array Type="system:Int32" x:Key="DecimalsArray">
<system:Int32>7</system:Int32>
<system:Int32>5</system:Int32>
<system:Int32>3</system:Int32>
<system:Int32>8</system:Int32>
</x:Array>
</UserControl.Resources>
<UserControl.DataContext>
<soDataGridProjectsHelpAttempt:MainSubViewModel/>
</UserControl.DataContext>
<StackPanel>
<ComboBox ItemsSource="{StaticResource DecimalsArray}"
Width="Auto"
SelectedItem="{Binding SelectedComboItem}"/>
<Button Command="{Binding Command}">Press me!!!</Button>
</StackPanel>
3. MainSubControl ViewModel:
public class MainSubViewModel : BaseObservableObject
{
private int _selectedComboItem;
private ICommand _command;
private bool _isControlVisible;
public MainSubViewModel()
{
IsControlVisible = true;
}
public ICommand Command
{
get { return _command ?? (_command = new RelayCommand(CommandMethod)); }
}
private void CommandMethod()
{
if (SelectedComboItem == 8)
IsControlVisible = false;
}
public bool IsControlVisible
{
get { return _isControlVisible; }
set
{
_isControlVisible = value;
OnPropertyChanged();
}
}
public int SelectedComboItem
{
get { return _selectedComboItem; }
set
{
_selectedComboItem = value;
OnPropertyChanged();
}
}
}
4. SecondSubControl:
<UserControl x:Class="SoDataGridProjectsHelpAttempt.SubSubControl"
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>
<Image Source="2014_8_27_Bing_en-AU.jpg" Margin="50"></Image>
</Grid>
5. App.xaml (put into Application.Resources):
<BooleanToVisibilityConverter x:Key="Bol2VisibilityConverter" />
regards,
your problem is that et goes out of scope, so after the function is doesn't exist anymore. you need to create it "outside" in a scope where it will still exist before and after that function.
So for example if there's a class called Application and that class holds the current control that your Button_click is attached to, you need to create the other control there too. Or at least the et variable if you don't want to create the EightTiles until you need it.
In my WPF application I use Caliburn.Micro (2.0.1). In App.xaml I declare BooleanToVisibilityConverter
<BooleanToVisibilityConverter x:Key="BoolToVis" />
Now when I want use in one of my view this converter I wrote something like that
<Button x:Name="MyButton" Visibility="{Binding visibility, Converter={StaticResource BoolToVis} }"/>
Everything works great but now I must use this converter in my MainVeiew. This View is my primary view. When application starts it's throw exception
System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
It is verry strange for me because if I write in my View
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis2" />
</Window.Resources>
and use BoolToVis2 instead of BoolToVis everything works fine. It i no big deal but I dont understand this behaviour.
Sample code of applcation:
App.xaml
<Application x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
>
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:AppBootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</ResourceDictionary>
</Application.Resources>
</Application>
AppBootstrapper
public class AppBootstrapper:BootstrapperBase
{
public AppBootstrapper()
{
Initialize();
DisplayRootViewFor<MainViewModel>();
}
}
MainViewModel
public class MainViewModel : Screen
{
bool _visibility;
public bool Visibility
{
get { return _visibility; }
set
{
_visibility = value;
NotifyOfPropertyChange("Visibility");
}
}
protected override void OnActivate()
{
base.OnActivate();
Visibility = false;
}
}
MainView
<Window x:Class="Test.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainView" Height="300" Width="300">
<Grid>
<Button x:Name="MyButton" Content="Test" Visibility="{Binding Visibility, Converter={StaticResource BoolToVis}}" />
</Grid>
Visibility property for any UIElement gets values from Visibility enumerator.
instead of using boolean use Visible,Hidden or Collapsed.
EDIT: It seems like that I needed to change the height of RowDefinition. Thanks goes to Alvaro. However:
how do I reference different elements inside my usercontrol (change their properties), when I want to change them in MainWindow.xaml and MainWindow.xaml.cs?
I have two XAML files in the same namespace.
MainWindow.xaml
List.xaml
When I try to add List.xaml usercontrol to my mainwindow xaml (that is insert xaml from another file), it does not show up.
I insert usercontrol that exists in Lemosystem namespace and inside View folder.
xmlns:lemoview="clr-namespace:Lemosystem.View"
I add usercontrol to my MainWindow.xaml:
<lemoview:List/>
Nothing shows up. Here is my List XAML (code is the default):
<UserControl x:Class="Lemosystem.View.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="What do you want to do today?" HorizontalAlignment="Left" Margin="10,96,-83,0" VerticalAlignment="Top" Height="44" Width="373" FontSize="24" FontWeight="Bold"/>
</Grid>
</UserControl>
I expect the label from my usercontrol to show up in MainWindow.xaml GUI, but it doesn't.
MainWindow.xaml
<Window x:Class="Lemosystem.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lemocontroller="clr-namespace:Lemosystem.Controller"
xmlns:lemoview="clr-namespace:Lemosystem.View"
Title="{Binding Path=SystemName}" Height="603" Width="827"
ResizeMode="NoResize" WindowStartupLocation="Manual"
>
<Grid Name="Window" Margin="0,0,2,0">
<Grid.RowDefinitions>
<RowDefinition Height="0*"/>
<RowDefinition/>
</Grid.RowDefinitions>
...
<lemoview:List/>
...
</Grid>
</Window>
And how do I reference different elements inside my usercontrol (change their properties), when I want to change them in MainWindow.xaml and MainWindow.xaml.cs?
So, I created a project with :
List.Xaml
<UserControl x:Class="WpfApplication1.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="{Binding TextToDisplay}"
HorizontalAlignment="Left"
Margin="10,96,-83,0"
VerticalAlignment="Top"
Height="44"
Width="373"
FontSize="24"
FontWeight="Bold" />
</Grid>
</UserControl>
ListViewModel.cs:
public class ListViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private string textToDisplay;
public string TextToDisplay
{
get { return textToDisplay; }
set { textToDisplay = value; OnPropertyChanged("TextToDisplay"); }
}
public ListViewModel(string value)
{
TextToDisplay = value;
}
}
}
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"
Title="MainWindow" Height="350" Width="525"
xmlns:lemoview="clr-namespace:WpfApplication1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Content="Click Me" HorizontalAlignment="Center" Click="Button_OnClick"></Button>
<ListView Grid.Row="1" ItemsSource="{Binding MyList}"></ListView>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyList=new ObservableCollection<ListViewModel>();
}
private ObservableCollection<ListViewModel> myList;
public ObservableCollection<ListViewModel> MyList
{
get { return myList; }
set { myList = value; }
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
MyList.Add(new ListViewModel("MyValue"));
}
}
App.xaml:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<DataTemplate DataType="{x:Type wpfApplication1:ListViewModel}">
<wpfApplication1:List />
</DataTemplate>
</Application.Resources>
in App.xaml, I just defined the binding between List.xaml and ListViewModel.cs
the viewModel of MainWindow is itself.
after every Click on the button, a new ViewModel is created, added to the list with a defined value (you will need to modify this part, to set the value you want).
I hope it will help you ! it works for me.
How do you like to show something, if you put it il a row that has height ="0" ?
change it to :
<Window x:Class="Lemosystem.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lemocontroller="clr-namespace:Lemosystem.Controller"
xmlns:lemoview="clr-namespace:Lemosystem.View"
Title="{Binding Path=SystemName}" Height="603" Width="827"
ResizeMode="NoResize" WindowStartupLocation="Manual"
>
<Grid Name="Window" Margin="0,0,2,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<lemoview:List/>
</Grid>
This is out of curiousity question. I know you should not structure any real WPF applications this way.
Working within and using only the MainWindow Class how do you bind an XAML element to a CLR property?
Here is my XAML.
<Window x:Class="WpfApplication1.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>
<TextBlock DockPanel.Dock ="Top" Height="50" Width="50"
Background ="AliceBlue" FontSize ="16" />
</Grid>
</Window>
And Code
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
string _myString = "hello world";
public string MyString
{
get { return _myString; }
}
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
}
So I want to display the string in the textblock. I think its a simple binding but I can't find the right syntax. Thanks
You must set your window data context to itself.
<Window.DataContext>
<Binding RelativeSource="{RelativeSource Self}"/>
</Window.DataContext>
then you cant bind to your property MyString
<TextBlock DockPanel.Dock ="Top" Height="50" Width="50"
Background ="AliceBlue" FontSize ="16" />
In this case you can simply do:
<Window x:Class="WpfApplication1.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"
x:Name="MainWindow">
<Grid>
<TextBlock DockPanel.Dock ="Top" Height="50" Width="50"
Background ="AliceBlue" FontSize ="16"
Text="{Binding MyString, ElementName=MainWindow}" />
</Grid>
</Window>