How to set "ResourceDictionary" as the content of the "Window" in WPF - wpf

I am trying to set a ResourceDictionary as the content of window in WPF. technically we can initialize a window with the corresponding view model. but when it comes to the output then the view is coming with the namespace of the view model, not with associated ResourceDictionary for the relevant view model. here is the tried example and output window. Please help me to resolve this problem.
public void ShowDialog(IDocumentPublishDialogViewModel dialogViewModel)
{
if (dialogViewModel is ContinuousJournalPrintViewModel)
{
Window continuousJournalPrintWindow = new ContinuousJournalPrintWindow
{
Owner = Application.Current.MainWindow,
Title = "New Continuous Journal Print",
Content = dialogViewModel
};
continuousJournalPrintWindow.Show();
}
else
{
PrepareCloseAction(dialogViewModel);
if (dialogViewModel is ChooseDraftOrTasksViewModel)
{
GuiDispatcherField.Invoke(() => DialogServiceField.ShowPopupDialog(dialogViewModel, dialogViewModel.CloseAction, () => true, true));
}
else
{
GuiDispatcherField.Invoke(() => DialogServiceField.ShowPopupDialog(dialogViewModel, dialogViewModel.CloseAction, () => true, true, HorizontalAlignment.Stretch, VerticalAlignment.Stretch));
}
}
}
<ResourceDictionary x:Class="DIPSASD.DynamicPublish.Client.Views.Previews.ContinuousJournalPrintView"
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:dc="http://DIPSASD.no/Arenade/UI"
xmlns:local="clr-namespace:DIPSASD.DynamicPublish.Client.ViewModels.Previews"
mc:Ignorable="d">
<DataTemplate DataType="{x:Type local:ContinuousJournalPrintViewModel}">
<dc:TextBlock Text="Team Y-KNOTS"></dc:TextBlock>
</DataTemplate>
[![enter image description here][1]][1]

Related

TextBlock content becomes invisible when TreeViewItem Header is selected

Included below is the source to a simple WPF application which uses a TreeView. Here's what it looks like when run:
Note however that if I click on one of the TreeViewItem headers:
the text in the TreeViewItem is no longer visible.
What's a good way to fix this so that the text remains visible when the header is selected?
As you can see, the code is primarily in C# so C#-based answers are preferred, but XAML is welcome too; I'll just convert it to C#.
UPDATE
If I set the Foreground of the TextBlock explitly to Black as suggested in an answer below:
{
var tree_view_item = new TreeViewItem() { Header = "abc" };
tree_view_item.Items.Add(new ScrollViewer() { Content = new TextBlock() { Text = "123", Foreground = new SolidColorBrush(Colors.Black) } });
tree_view.Items.Add(tree_view_item);
}
it does indeed appear to help:
However, if I then select the TextBlock, the textblock is shown as black on blue which is a little awkward:
Is there a way to also change the background color used when the item is highlighted?
MainWindow.xaml:
<Window x:Class="TreeViewItemHighlightColor.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:TreeViewItemHighlightColor"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace TreeViewItemHighlightColor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var tree_view = new TreeView();
{
var tree_view_item = new TreeViewItem() { Header = "abc" };
tree_view_item.Items.Add(new ScrollViewer() { Content = new TextBlock() { Text = "123" } });
tree_view.Items.Add(tree_view_item);
}
{
var tree_view_item = new TreeViewItem() { Header = "bcd" };
tree_view_item.Items.Add(new ScrollViewer() { Content = new TextBlock() { Text = "234" } });
tree_view.Items.Add(tree_view_item);
}
{
var tree_view_item = new TreeViewItem() { Header = "cde" };
tree_view_item.Items.Add(new ScrollViewer() { Content = new TextBlock() { Text = "345" } });
tree_view.Items.Add(tree_view_item);
}
Content = tree_view;
}
}
}
There's a chance that the Foreground property of the TextBlock is being inherited and altered by the state of the TreeViewItem.
Set the Foreground property of the TextBlock to black. That way, the TreeViewItem will not override it.

How to install these Pie Chart controls in Visual Studio?

https://www.codeproject.com/Articles/442506/Simple-and-Easy-to-Use-Pie-Chart-Controls-in-WPF
Can't seem to get these working in my WPF project. How do I add the references to get going with this pie chart?
You need to sign in and download the binaries. You should then unpack the zip file and add a reference (Project->Add Reference->Browse->Browse in Visual Studio) to the downloaded and unpacked PieControls.dll file. After you have done this, the following sample code should work.
MainWindow.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:pie="clr-namespace:PieControls;assembly=PieControls"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Grid>
<pie:PieChart x:Name="chart1" Width="260" Height="140" PieWidth="120" PieHeight="120"/>
</StackPanel>
</Window>
MainWindow.xaml.cs:
using PieControls;
...
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ObservableCollection<PieSegment> pieCollection = new ObservableCollection<PieSegment>();
pieCollection.Add(new PieSegment { Color = Colors.Green, Value = 5, Name = "Dogs" });
pieCollection.Add(new PieSegment { Color = Colors.Yellow, Value = 12, Name = "Cats" });
pieCollection.Add(new PieSegment { Color = Colors.Red, Value = 20, Name = "Mice" });
pieCollection.Add(new PieSegment { Color = Colors.DarkCyan, Value = 22, Name = "Lizards" });
chart1.Data = pieCollection;
}
}

WPF page fixed layout with MVVM

I have a WPF application with MVVM that have several pages with common layout e.g. page header and navigation buttons (the middle part of each page is different).
How can I implement the fixed page layout once and extend it in the different pages with MVVM?
In my opinion, the best way to do this is to create a main window or page and then render user controls inside of that using a content control and data templates. Set the content control binding to a property on the main window's view model. You'll need an implementation of INotifyPropertyChanged, of course, then a main window or application view model, some child view models, a content control in your main window or page, then user controls to represent your views...sort of this this:
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(property));
}
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected virtual void VerifyPropertyName(string property)
{
if (TypeDescriptor.GetProperties(this)[property] == null)
{
throw new Exception(property + " property doesn't exist!");
}
}
}
public interface IPageViewModel
{
string Name { get; }
}
public class Page1ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class Page2ViewModel : ObservableObject, IPageViewModel
{
public string Name { get { return "View 1"; } }
}
public class ApplicationViewModel : ObservableObject
{
private IPageViewModel currentViewModel;
public IPageViewModel CurrentViewModel
{
get
{
return this.currentViewModel =
this.currentViewModel
?? new Page1ViewModel();
}
set
{
this.currentViewModel = value;
OnPropertyChanged("CurrentViewModel");
}
}
public ApplicationViewModel()
{
this.CurrentViewModel = new Page1ViewModel()
}
}
Your main window or page would have its view model (DataContext) set to an instance of ApplicationViewModel. The content control would then be bound to the CurrentViewModel property of the ApplicationViewModel, like this:
<Window x:Class="WpfScratchApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfScratchApp"
Title="MainWindow" Height="350" Width="525"
DataContext="{DynamicResource AppViewModel}"
>
<Window.Resources>
<ResourceDictionary>
<app:ApplicationViewModel x:Key="AppViewModel" />
</ResourceDictionary>
</Window.Resources>
<Grid>
<!-- Buttons and stuff -->
<ContentControl Content="{Binding CurrentViewModel}" />
</Grid>
</Window>
Then, create UserControl's corresponding to each of those views:
<UserControl x:Class="WpfScratchApp.Views.Page1View"
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="150" d:DesignWidth="150">
<!-- Cool controls and stuff in here... -->
</UserControl>
(Create a similar one corresponding to Page2ViewModel, called "Page2View".) Then, map the view models to the views like this in your app.xaml, or a merged dictionary.
<Application x:Class="WpfScratchApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:PortfolioManager"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:Page1ViewModel}">
<views:Page1View />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:Page2ViewModel}">
<views:Page2View />
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
When you change the CurrentViewModel property in the application view model, it should change the value of the binding for the control control. WPF will use the data template corresponding to the type represented by the CurrentViewModel property to render the content.
So, you can have your buttons all set up in the main window and coded to operate on the CurrentViewModel. Then, change out the CurrentViewModel based upon the content you want to show.

Dynamically creating buttons in WPF xaml file/xaml.cs file after reading an xml file?

I am new to WPF,
Problem Statement: I have a xml file that gives me the number of items that i need to create,
for each item, i need a button.
If there are 20 items---> on loading the xaml file,
the xml will be read,
count(of number of items) will be read and created.
Is there a way to do this in xaml file?
Here is a simple/quick fix:
Expose a Panel (say StackPanel) in the Xaml and add the new buttons to them as Children on run time...
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Loaded="Window_Loaded">
<StackPanel x:Name="mainPanel"/>
</Window>
MainWindow.xaml.cs
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var buttonNames = new List<string>();
// Parse the XML, Fill the list..
// Note: You could do it the way you prefer, it is just a sample
foreach (var buttonName in buttonNames)
{
//Create the button
var newButton = new Button(){Name = buttonName};
//Add it to the xaml/stackPanel
this.mainPanel.Children.Add(newButton);
}
}
Solution using Data Binding
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" >
<ItemsControl ItemsSource="{Binding YourCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Window>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
YourCollection = new List<Button>();
// You could parse your XML and update the collection
// Also implement INotifyPropertyChanged
//Dummy Data for Demo
YourCollection.Add(new Button() { Height = 25, Width = 25 });
YourCollection.Add(new Button() { Height = 25, Width = 25 });
this.DataContext = this;
}
public List<Button> YourCollection { get; set; }

Invoke Command Within Custom User Control

I'm new to WPF and i'm trying to learn the famous MVVM pattern,
I'm facing a small issue (i'm sure) when i try to bind simple command to some ViewModel
this is Simple UserControl i've created:
<UserControl x:Class="MVVM_UsingUserControl_Sample.View.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
>
<StackPanel DataContext="MyUserControlViewModel" Orientation="Vertical" >
<Button Margin="0,100,0,0" Height="50" Width="50" Content="PressMe" Command="{Binding Path=MyCommand}"/>
</StackPanel>
</UserControl>
and this is the User Control ViewModel
class MyUserControlViewModel : ViewModelBase
{
CommandBase m_MyCommand = null;
public MyUserControlViewModel()
{
}
public ICommand MyCommand
{
get
{
if (m_MyCommand == null)
{
m_MyCommand = new CommandBase(new Action<object>(DoSomething),
new Predicate<object>(CanDoSomething));
}
return m_MyCommand;
}
}
public void DoSomething(object i_Params)
{
MessageBox.Show("Inside MyUserControl DoSomething");
}
public bool CanDoSomething(object i_Params)
{
return true;
}
}
this is the Main window xaml (no code behaind)
Now the problem is :
My main window contains the userControl as is (inside stack panel) and nothing else.
i expect the command "MyCommad" will get invoke when i press the button "MyButton"
but it doesn't.
anyone has idea why ???
Big thanks.
In the constructor of your main window, set its DataContext to your ViewModel.
For example,
this.DataContext = new MyViewModel();
In your XAML, remove
DataContext="MyUserControlViewModel"
since the DataContext will inherit from the main window.
Everything should then work as you expect.

Resources