UWP Popup class bug - c#

I have created a simple notepad. I am unable to assign a User Control to the Child property of Popup. Every time I do it throws an exception of type System.ArgumentException. When I instantiate the User Control in code it works fine.
User control is called WrapOptionsDialog.
<Page.Resources>
<local:WrapOptionsDialog x:Key="wrapOptionsDialog" />
</Page.Resources>
<Grid>
<TextBox Name="txtbox"
IsEnabled="False"
FontSize="24"
AcceptsReturn="True"
TextWrapping="{Binding Source={StaticResource wrapOptionsDialog}, Path=TextWrapping, Mode=TwoWay}"/>
</Grid>
WrapOptionsDialog wrapOptionsDialog = this.Resources["wrapOptionsDialog"] as WrapOptionsDialog;
// Create popup
Popup popup = new Popup
{
Child = wrapOptionsDialog,
IsLightDismissEnabled = true,
};
Below in comment I'm going to link the actual project. Exception occurs after clicking on Wrap Option button. Please help.

Related

Change Windows Content Control From User Control - WPF

In my project I have a Window called AccountWindow.xaml which has a ContentControl to display the two UserControls.
AccountWindow
<Window>
<Window.Resources>
<!-- Login User Control Template -->
<DataTemplate x:Name="LoginUserControl" DataType="{x:Type ViewModels:LoginViewModel}">
<AccountViews:LoginUserControl DataContext="{Binding}"/>
</DataTemplate>
<!-- Registration User Control Template -->
<DataTemplate x:Name="RegistrationUserControl" DataType="{x:Type ViewModels:RegistrationViewModel}">
<AccountViews:RegistrationUserControl DataContext="{Binding}" />
</DataTemplate>
</Window.Resources>
<Grid>
<!-- ContentControl that displays the two User Controls -->
<ContentControl Content="{Binding}" />
</Grid>
</Window>
I then have two user controls called LoginUserControl and RegistrationUserControl
Login User Control
<Grid Background="Pink">
<Button Content="Switch To Register View" Command="{Binding SwitchToReg}" Margin="100" />
</Grid>
Register User Control
<Grid Background="Orange">
<Button Content="Press Me" Command="{Binding PressMe}" Margin="100" />
</Grid>
Both the Login User Control and the Registration User Control have their own ViewModels with a RelayCommand inside that is bound to the buttons as shown in the code.
Login View Model
public class LoginViewModel
{
public RelayCommand SwitchToReg
{
get
{
return new RelayCommand(param =>
{
Console.WriteLine("Switch To Reg");
// Somehow change the content control in the AccountWindow to show the RegistrationDataTemplate???
});
}
}
}
The Problem
I want to be able to change the content of the ContentControl in the AccountWindow when the user presses on one of the buttons in the UserControls. For example, when the user presses the button in the Login User Control called "Switch To Register View" it executes a the Command SwitchToReg and changes the content control to RegistrationUserControl & its ViewModel. How could this be possible?
To achieve that you would need to pass a reference for the AccountWindow into the UserControl when you are constructing it and then your Command can update the ContentControl using the reference you have provided.
This is introducing coupling which is better to avoid so instead I would suggest thinking about the design of the AccountWindow. I would use grid rows to separate the ContentControl area from the button which will change the UserControl.
In the window above, the blue area is where I would host the ContentControl and the red area is part of the AccountWindow.
This way, the behaviour for switching the ContentControl is entirely handled by the AccountWindow.
You can create a property and attache it to the control.
Or you can create another user control and make it visible o not controled by the property that you created.

Invoke search in Avalon Editor using Button click

I am using AvalonEditor inside a window dialog(WPF). Window dialog host TextEditor control. I have Find button explicit on Window. On click of Button, Search should work inside TextEditor. Can you please suggest how to bind Button Find to invoke TextEditor Search.
Currently, I have edited the TextEditor constructor to install the SearchPanel. And when Ctrl + F is pressed inside TextEditor, default search dialog appears.
I want the same thing to work on Button click, but using MVVM approach.
Please suggest.
WPF XAML code
<Window>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Left">
<Button Name="FindButton" Content="Find" Margin="2" Style="{DynamicResource ButtonFooter_Style}" >
<Button.CommandBindings>
<CommandBinding Command="ApplicationCommands.Find" CanExecute="CommandBinding_CanExecute">
</CommandBinding>
</Button.CommandBindings>
</Button>
<avalonEdit:TextEditor Grid.Row="2" Grid.Column="1" Name="textEditor"
FontFamily="Consolas"
FontSize="10pt"
SyntaxHighlighting="XML" ShowLineNumbers="True" >
</avalonEdit:TextEditor>
</Window>
TextEditor.cs class constructor already been edited
public TextEditor() : this(new TextArea())
{
Search.SearchPanel.Install(this.TextArea);
}
to have find feature enabled on pressing Ctrl + F
Now I want Find button to invoke Search feature without pressing Ctrl + F.
-Thanks
In code behind...
create a member:
private readonly SearchPanel searchPanel;
in your constructor, or in any block that suits your needs (it needs to happen only once):
searchPanel = SearchPanel.Install(textEditor);
and then in the event handling code:
searchPanel.SearchPattern = "eg. your selected text";
searchPanel.Open();
searchPanel.Reactivate();;

Element is already the child of another element when doesnt exist?

I'm trying to programatically create a button flyout, within my XAML I have:
<Page.Resources>
<Button x:Key="LaunchFlyout" Content="LAUNCH">
<Button.Flyout>
<Flyout Placement="Top">
<Grid Width="200" Height="200">
<StackPanel>
<Rectangle Fill="Red" Width="100" Height="100" />
<Rectangle Fill="Green" Width="100" Height="100" />
</StackPanel>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</Page.Resources>
Nested within grids I have:
<Grid x:Name="launchBtn_grid" Grid.Column="1">
</Grid>
And then in my code within the Page_Loaded method I have:
bool hasContainer = localSettings.Containers.ContainsKey("appStatus");
if (!hasContainer) {
Button button = (Button)this.Resources["LaunchFlyout"];
launchBtn_grid.Children.Add(button);
}
else {
Button button = new Button();
button.Content = "LAUNCH";
button.Click += launch_btn_Click;
launchBtn_grid.Children.Add(button);
}
When I debug this, it reaches the IF statement and reaches this line launchBtn_grid.Children.Add(button); and then I get this error Element is already the child of another element.
Does anyone understand why? I have already looked and they dont already exist so I don't understand why it is giving me this error. Does anyone know what I am doing wrong?
I'm not sure in what context/use case your are doing that, but it feels weird to me to have an actual control as a Resource (not a DataTemplate, Style, etc).
If you only want to have 1 button of the 2 different template, why not switch Visibility on the 2 instead of loading controls from your code behind ?
Going forward with the idea, just add both buttons in the Grid within your XAML and switch their Visibility according to the setting you read.
There is a BooleanToVisibilityConverter within the framework to help you with this.

WPF TabItem not highlighted it should

I have three tabs. By simply being clicked individually, they will be highlighted individually as they should.
There are RelyCommand behind these tabs. Whenever the mune is clicked, the program should bring back the first TabItem and it should be highlighted. However, when the second tab is clicked, the first tab would not be highlighted as it should, although it behaves like it does get clicked. It is just not highlighted.
Here is the code behind
xaml code for the two tabs at View level:
<StackPanel Orientation="Horizontal"
Background="{x:Null}">
<TabControl Height="50" Margin="12,0,0,0">
<TabItem Name="tiCaptureSetup" IsSelected="{Binding Path=IsCaptureSetupTabSelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<TabItem.Header>
<Button Name="btnCaptureSetup"
Grid.Column="0"
Width="90"
Height="40"
Margin="5"
ToolTip="Capture Setup"
Content="Capture Setup"
Click="btnCaptureSetup_Click"
IsEnabled="{Binding Path=CaptureSetupButtonStatus, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsDefault="True"
></Button>
</TabItem.Header>
</TabItem>
<TabItem Name="tiCapture" IsSelected="{Binding Path=IsCaptureTabSelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<TabItem.Header>
<Button Name="btnCapture"
Grid.Column="0"
Margin="5"
Width="90"
Height="40"
ToolTip="Capture"
Content="Capture"
Click="btnCapture_Click"
IsEnabled="{Binding Path=CaptureButtonStatus, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"></Button>
</TabItem.Header>
</TabItem>
The C# code at ViewModel level (CaptureSetup() is the RelyCommand for clicking the first tab, and HardwareSetupLS() is the RelyCommand for the pop-up window on the menu, and RefereshCaptureSetup() is basically trying to retrieve the first tab when the menu window pops up)
public void CaptureSetup()
{
Command command = new Command();
command.Message = "Capture Setup";
command.CommandGUID = new Guid("6ecb028e-754e-4b50-b0ef-df8f344b668e");
_eventAggregator.GetEvent<CommandShowDialogEvent>().Publish(command);
}
public void HardwareSetupLS()
{
//RefereshCaptureSetup(); // refresh panel when hardware setting window is loaded.
Command command = new Command();
command.Message = "HardwareSetupLS";
command.CommandGUID = new Guid("64c695e6-8959-496c-91f7-5a9a95d91e0d");
_eventAggregator.GetEvent<CommandShowDialogEvent>().Publish(command);
RefereshCaptureSetup();
}
public void RefereshCaptureSetup() // refresh CaptureSetup UI
{
_isCaptureSetupTabSelected = true;
_isCaptureTabSelected = false;
_isReviewTabSelected = false;
Command command = new Command();
command.Message = "Capture Setup";
command.CommandGUID = new Guid("{6ecb028e-754e-4b50-b0ef-df8f344b668e}");
_eventAggregator.GetEvent<CommandShowDialogEvent>().Publish(command);
}
I am very confused at this point what else I can do to make the first TabItem highlighted as it should.
I feel like there is some important logic missing in your question (e.g. how the IsCaptureSetupTabSelected and IsCaptureTabSelected are updated) but anyway here are three pointers from looking at your code:
UpdateSourceTrigger=PropertyChanged is useless since your bindings are OneWay (from the source in your ViewModel towards your UI, the source is never updated). If you have written some logic expected to receive IsSelected change notification upon mouse clicks, this won't happen.
You seem to be updating the inner properties wrapped by your bound properties (e.g. _isCaptureSetupTabSelected = true instead of IsCaptureSetupTabSelected = true ) and thus, could be missing the proper INotifyPropertyChanged event that the UI is expecting.
Make sure that the proper TabItem is on focus.

c# WPF how to produce a flashy warning

I'm learning WPF, so bear with me.
I would like to have my WPF application flash in the user's face if a certain event is fired.
What is the best way to "notify" the user? I really want the user to react!
Cheers, Patrick
Environment: Windows7/64bit/.Net4
If you want the user to react you can force them to by simply opening a modal dialogue. The most lightweight of which being the MessageBox. You can also create normal modal windows using their ShowDialog method, you can make those windows as "fancy" as you want by getting rid of their normal appearance. This is achieved by setting the WindowStyle to None and AllowsTransparency to true, this will remove all the frame elements, so the window is now pure content.
Popups are handy for non-modal notifications and they already are content-only, but setting their AllowsTransparency to true may also be desired if you want rounded corners for example.
Best is entirely subjective and depends on many context variables but here is how I do it MVVM style.
In your main view model, define a property
pubic ObservableCollection<AlertViewModel"> Alerts { get; private set; }
in my case the AlertViewModel has only a "Message" property and a "Dismiss" RelayCommand.
In the XAML of your main view add
<Grid>
<all of my other other view controls>
<ItemsControl x:Name="AlertsControl" Opacity="50" ItemsSource="{Binding Alerts}"/>
</Grid>
Make sure it is the last item in the main container of your main view. This ensures it has the highest z order and will appear on top of all other controls.
Here is the data template for this view model
<DataTemplate DataType="{x:Type vm:AlertViewModel}">
<Border CornerRadius="10" Margin="3" Background="Red">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Margin="10" Grid.Column="0"
Command="{Binding ElementName=theWindow, Path=DataContext.DismissAlarmCommand}"
CommandParameter="{Binding}">Dismiss</Button>
<TextBlock Foreground="White" FontWeight="ExtraBold" Grid.Column="1"
Text="{Binding Message}" FontSize="20"
VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
</Grid>
</Border>
</DataTemplate>
Now,
Alerts.Add( new AlertViewModel() { Message = "Danger Will Robinson! Danger!" } );
Will pop a Bright red alert box onto the top of your main form. It does not go away until the user presses "Dismiss"
If you want it to flash or fade in and out or bounce up and down you can add animation in the data template.
You can use a Converter or data to Enable/Disable the rest of the controls in the app byt binding to AlertsControl.HasItems
Good luck.

Categories

Resources