WPF data binding is not working for second usage - c#

I'm using GalaSoft.MvvmLight.Messaging for communication between classes.
From my ViewModel I'm asking for an object of type view to use it as the content of my DialogHost ( part of the MaterialDesign Framework ):
ViewModel:
Messenger.Default.Send(new NotificationMessage("dialogFormOpenStaple"));
-
private void DialogReceived(string msg, object param)
{
if (msg == "dialogFormOpenStaple")
{
this.dialogContent = param;
this.isDialogOpen = true;
}
}
View
private void NotificationMessageReceived(string msg)
{
if (msg == "dialogFormOpenStaple")
{
object content = new dialogEditMode();
Messenger.Default.Send(new NotificationMessage<object>(content, "dialogFormOpenStaple"));
}
}
All this is working fine. In my XAML itself I got some button bindings to RelayCommands.
<UserControl x:Class="kati2._0.production.dialogEditMode"
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:kati2._0.production"
mc:Ignorable="d"
>
[...]
<Button Margin="8 0 0 0" Style="{DynamicResource MaterialDesignFlatButton}" Foreground="#FF757476" IsDefault="True" Command="{Binding dialogOpenStapleNo}">No</Button>
[...]
</UserControl>
Those RelayCommands are defined in my ViewModel. When I open die Dialog for the first time and click on the button it's working fine. If I try it a second time the dialog also opens up but the click event is not getting triggered.

Related

Show Initial Dialog before MainWindow in WPF Material Design

I am using MaterialDesign for my WPF project which downloads json from remote server and parse.
Before showing MainWindow, I want to open initial loading dialog to show how much loading is completed.
MainWindow.xaml
<materialDesign:DialogHost Identifier="RootDialog" CloseOnClickAway="False">
<TextBlock Text="Loading Completed." />
</materialDesign:DialogHost>
MainWindowViewModel.cs
public class MainWindowViewModel: BaseViewModel
{
public MainWindowViewModel(Window mWindow) {
...
ShowInitialDialog();
...
}
private async void ShowInitialDialog()
{
var view = new LoadingDialog();
//show the dialog
var result = await DialogHost.Show(view, "RootDialog", null, null);
//check the result...
Debug.WriteLine("Dialog was closed, the CommandParameter used to close it was: " + (result ?? "NULL"));
}
}
LoadingDialog.xaml
<UserControl 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:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
mc:Ignorable="d">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="10">
<ProgressBar Width="60" Height="60" Margin="16"
Style="{DynamicResource MaterialDesignCircularProgressBar}"
IsIndeterminate="True"
Value="33"/>
<TextBlock Text="{Binding Notification}" HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</UserControl>
But when I ran the code, it shows error "DialogHost Instance not exist".
How do I get to know when the "RootDialog" DialogHost is instatiated?
Wait intil the DialogHost instance in the window has been loaded:
public class MainWindowViewModel : BaseViewModel
{
public MainWindowViewModel(Window mWindow)
{
mWindow.rootDialog.Loaded += (s, e) => ShowInitialDialog();
}
private async void ShowInitialDialog()
{
var view = new LoadingDialog();
//show the dialog
var result = await DialogHost.Show(view, "RootDialog", null, null);
//check the result...
Debug.WriteLine("Dialog was closed, the CommandParameter used to close it was: " + (result ?? "NULL"));
}
}
XAML:
<materialDesign:DialogHost x:Name="rootDialog" x:FieldModifier="internal"
Identifier="RootDialog" />
As a side note, a view model having a strong reference to a window breaks the MVVM pattern.

Is there a way a TextBox loses focus when clicking on the background in Caliburn Micro?

When trying to rebuild a WPF Application to use Caliburn Micro I experienced that a TextBox does not loose focus when you click outside of it. Is there a fix for that behaviour?
I am using Caliburn Micro 3.2.0. I tried using older versions but this problem persits.
XAML:
<Window x:Class="WPFUI.Views.ShellView"
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:WPFUI.Views"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800">
<Grid>
...
<WrapPanel>
<TextBox x:Name="Name" MinWidth="50"
cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
[Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
</TextBox>
...
</WrapPanel>
...
</Grid>
</Window>
I assume this is a case where you do not have any other Element in the Window other than the Textbox, which is why it cannot lose focus. One way to achieve this is to make the Window Focusable and setting Focus to it using a behavior.
For Example, assuming your Xaml to be as follows
<Window x:Class="CM.WPFApp2019.Views.ShellView"
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:cal="http://www.caliburnproject.org"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CM.WPFApp2019.Views"
xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviors="clr-namespace:CM.WPFApp2019.ViewModels"
mc:Ignorable="d" Focusable="True"
Title="ShellView" Height="450" Width="800">
<i:Interaction.Behaviors>
<behaviors:ClearFocusOnClickBehavior ElementToClearFocus="{Binding ElementName=Name}"/>
</i:Interaction.Behaviors>
<Grid>
<WrapPanel>
<TextBox x:Name="Name" MinWidth="50" Focusable="True"
cal:Message.Attach="[Event LostFocus] = [Action Name_LostFocus()];
[Event PreviewTextInput] = [Action Name_PreviewTextInput($source, $eventArgs)]">
</TextBox>
</WrapPanel>
</Grid>
</Window>
Please note I have added a Behavior called ClearFocusOnClickBehavior to the Window. Also you have set the Focusable Property of Window to be true.
Now you can define the behavior as follows
public class ClearFocusOnClickBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty ElementToClearFocusProperty = DependencyProperty.RegisterAttached("ElementToClearFocus", typeof(FrameworkElement),
typeof(ClearFocusOnClickBehavior), new UIPropertyMetadata());
public FrameworkElement ElementToClearFocus
{
get { return (FrameworkElement)GetValue(ElementToClearFocusProperty); }
set { SetValue(ElementToClearFocusProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.MouseDown += (sender, args) =>
{
FrameworkElement ctrl = ElementToClearFocus;
FrameworkElement parent = (FrameworkElement)ElementToClearFocus.Parent;
while (parent != null && parent is IInputElement
&& !((IInputElement)parent).Focusable)
{
parent = (FrameworkElement)parent.Parent;
}
DependencyObject scope = FocusManager.GetFocusScope(ElementToClearFocus);
FocusManager.SetFocusedElement(scope, parent as IInputElement);
};
base.OnAttached();
}
}
The Behavior would add a MouseDown event for the associated object, where you could trace the Parent of the ElementToClearFocus Control which can be Focused. In this case, since you have set the Window as focusable, it would receive the Focus. The Textbox in turn loses the focus and raises the Name_LostFocus method

show dialog with WPF window under Outlook VSTO add-in

I created Outlook VSTO application. I want to popup a WPF window dialog when click button. Here is my WPF window:
<Window x:Class="WorkflowSR.View.ArchiveSettingWindow"
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:WorkflowSR.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<CheckBox x:Name="checkBox" Content="CheckBox" HorizontalAlignment="Left" Margin="111,73,0,0" VerticalAlignment="Top" Width="100"/>
</Grid>
</Window>
In code, when I want to open dialog, I do like this:
var archiveSettingWindow = new ArchiveSettingWindow();
archiveSettingWindow.owner = ???
archiveSettingWindow.ShowDialog();
What should I set for the window owner? Thank you.
Use IOleWindow and WindowInteropHelper:
using System.Runtime.InteropServices;
...
IntPtr wnd = new IntPtr(0);
object window = _application.ActiveWindow();
if (window != null)
{
IOleWindow oleWindow = window as IOleWindow;
if (oleWindow != null)
{
oleWindow.GetWindow(out wnd);
}
}
...
if (wnd != IntPtr.Zero)
{
WindowInteropHelper helper = new WindowInteropHelper(archiveSettingWindow);
helper.Owner = wnd;
archiveSettingWindow.ShowInTaskbar = false;
}

How to generate GUI dynamically using WPF-MVVM

I am working on a wpf application strictly using MVVM. What i want to do is pop up a window which will pop up on a button click.
This window size will be determined dynamically depending upon the input that i have received from the pervious form submission on button click.
If the input given was 1 then on this window i will have GUI like: (where * represents the boundary)
********************************************
GUI : some textbox and buttons
********************************************
If the input given was 2 :
********************************************
GUI : some textbox and buttons
********************************************
********************************************
GUI : some textbox and buttons
********************************************
How to do this using MVVM approach ? Should i code for it using c# (because the input will be given dynamically)
What i have done is (tableView.xaml, on which will contain the GUI i shown you previously):
<UserControl x:Class="DBPythonAndXmlGenerator.View.tableView"
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:local="clr-namespace:DBPythonAndXmlGenerator.ViewModel"
xmlns:converters="clr-namespace:DBPythonAndXmlGenerator.converters"
>
<UserControl.Resources>
<converters:Table x:Key="TableCoverter" />
</UserControl.Resources>
<Grid>
</Grid>
</UserControl>
And my button click function (MVVM) is below:
public ICommand SavePersonCommand
{
get
{
if (savePersonCommand == null)
savePersonCommand = new DelegateCommand(new Action(SaveExecuted), new Func<bool>(SaveCanExecute));
return savePersonCommand;
}
}
public bool SaveCanExecute()
{
return !string.IsNullOrEmpty(DB_Col.DbName) && !string.IsNullOrEmpty(DB_Col.NumTables);
}
public void SaveExecuted()
{
System.Windows.MessageBox.Show(string.Format("Saved: {0} {1} ", DB_Col.DbName, DB_Col.NumTables));
}
How to render data in this Grid dynamically using c# follwing MVVM If my approach is right?

NullReferenceException loading RenderWindowControl for vtk in WPF

I am trying to load a RenderWindowControl from vtk libraries on my WPF proyect using ActiViz.NET and Visual Studio 2013. The library works fine since I did a new project just to practice on itbut when I tried to integrate it into my work, I got a null RenderWindowControl this time. This is my code:
MainWindow.xaml:
<Window x:Class="myProject.Views.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"
xmlns:VtkTab="clr-namespace:myProject.Views.UITabs.VtkTab"
x:Name="Mainwindow"
MinHeight="600"
MinWidth="800"
Title="{Binding Title}"
Height="720"
Width="1280"
Icon="{StaticResource ApplicationIcon}"
Loaded="OnLoaded"
DataContext="{Binding Main, Source={StaticResource ViewModelLocator}}"
Style="{StaticResource WindowStyle}"
mc:Ignorable="d">
<DockPanel>
<TabControl>
....
....
<VtkTab:VtkTabView />
....
....
</TabControl>
</DockPanel>
</Window>
VtkTabView.xaml:
<UserControl x:Class="myProject.Views.UITabs.VtkTab.VtkTabView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vtk="clr-namespace:Kitware.VTK;assembly=Kitware.VTK"
Loaded="WindowLoaded"
Height="480" Width="640">
<WindowsFormsHost Name="Wfh">
<vtk:RenderWindowControl x:Name="RenderControl" />
</WindowsFormsHost>
</UserControl>
VtkTabView.xaml.cs:
public partial class UITabView
{
protected static Random _random = new Random();
vtkActor actor = vtkActor.New();
public VtkTabView()
{
InitializeComponent();
var sphere = vtkSphereSource.New();
sphere.SetThetaResolution(8);
sphere.SetPhiResolution(16);
var shrink = vtkShrinkPolyData.New();
shrink.SetInputConnection(sphere.GetOutputPort());
shrink.SetShrinkFactor(0.9);
var move = vtkTransform.New();
move.Translate(_random.NextDouble(), _random.NextDouble(), _random.NextDouble());
var moveFilter = vtkTransformPolyDataFilter.New();
moveFilter.SetTransform(move);
moveFilter.SetInputConnection(shrink.GetOutputPort());
var mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(moveFilter.GetOutputPort());
// The actor links the data pipeline to the rendering subsystem
actor.SetMapper(mapper);
actor.GetProperty().SetColor(1, 0, 0);
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
var renderer = RenderControl.RenderWindow.GetRenderers().GetFirstRenderer();
renderer.AddActor(actor);
}
}
RenderControl.RenderWindow is null on WindowLoaded (VtkTabView.xaml.cs) and I do not know why. Might it be because I load UITabView from a second xamp and I lose the content of RenderControl?, it is the only difference I see compare to the example I did.
Access the RenderWindow on Load event of the RenderWindowControl.
e.g.
public VtkTabView()
{
InitializeComponent();
// initialize your sphrere and actor
RenderControl.Load += MyRenderWindowControlOnLoad;
}
private void MyRenderWindowControlOnLoad(object sender_in, EventArgs eventArgs_in){
//access the RenderWindow here
}

Categories

Resources