wpf user control - how to set text from outer uc - c#

i have a problem , i have 2 uc that displayed in main windows.
i want when i press on button in the first uc the text in the other uc will change
this the axml i use and the code
first uc
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Width="40" Height="40" Name="playbtn" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0" Click="playbtn_Click" >
<Button.Content>
<Image Source="/img/player_play.png" ></Image>
</Button.Content>
</Button>
<Button Width="40" Height="40" Name="pausebtn" Grid.Column="1" Grid.Row="0" >
<Button.Content>
<Image Source="/img/player_pause.png" ></Image>
</Button.Content>
</Button>
<Button Width="40" Height="40" Name="stopbtn" Grid.Column="2" Grid.Row="0" >
<Button.Content>
<Image Source="/img/player_stop.png" ></Image>
</Button.Content>
</Button>
</Grid>
</StackPanel>
</Grid>
</StackPanel>
secound uc <TextBlock Name="Progresstimertext" Text="00:00:00" FontSize="20"></TextBlock>
so i want to press on start button and the timer will be change? how to
10x

This should be managed in the View Model of your Main Window, as this seems the only location that has knowledge of both controls and it sounds as though each of your user control's shouldn't necessarily have knowledge of each other.
Ideally, you should have a reference to each of your user controls in the code-behind (or view model class is you have a dedicated one).
If in code behind, you would simply expose these by giving them names.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="your controls reference here">
<Grid>
<Grid.ColumnDefinitions>
</ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:UserControl1 x:Name="Control1"/>
<controls:UserControl2 x:Name="Control2" Grid.Column="1"/>
</Grid>
</Window>
Now you can reference them in your code behind by name Control1 and Control2. These user control classes should be exposing the properties that you want to control, in your case ProgressTimerText, such that, in the code-behind, you can set it easily such as
Control2.ProgressTimerText = "00:00:00";
Where to do this? Well you probably want to create a Stopped event on your Control1, that you can attach to your code behind - in your case, something like Stopped. In your UserControl1 class you should declare something like
public event EventHandler Stopped;
And then in the local event handler for the Click of the stop button, invoke that event.
private void Stop_Click(object sender, RoutedEventArgs e)
{
if (Stopped != null)
Stopped(this, e);
}
Attach that in your MainWindow:
<controls:UserControl1 x:Name="Control1" Stopped=Control1_Stopped/>
Now in your code-behind you should have something like:
private void Control1_Stopped(object sender, RoutedEventArgs e)
{
Control2.ProgressTimerText = "00:00:00";
}

Related

How to make a custom Pop Up Dialogue reuseable

So I created a custom Pop Up dialogue box in UWP, to make it reusable, i made use it of a User Control
<UserControl
x:Class="ContentDialogueBox.PopUpCustomDialogueUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ContentDialogueBox"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<ContentDialog x:Name="MyContentDialogCustom"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Title="Lorem Ipsum"
PrimaryButtonText="OKxxx"
SecondaryButtonText="Canc"
Margin="0,0,-98,0" Width="1000" >
<Grid Background="Wheat">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Name" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox PlaceholderText="First Name" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="10"/>
<TextBlock Text="Middle Name" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1"/>
<TextBox PlaceholderText="Middle Name" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="10"/>
<TextBlock Grid.Row="2" Text="Name" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox PlaceholderText="First Name" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="10"/>
</Grid>
</ContentDialog>
</UserControl>
I was able to reference the user control in another page that contains the button named ButtonShowContentDialog4, what i want to achieve is display the PopUp Dialogue box, when i click the button in the page. Please how do i achieve this.
private void ButtonShowContentDialog4_Click(object sender, RoutedEventArgs e)
{
//show the PopUp here when this button is clicked
}
There are couple of ways to achieve that. Apart from the thing that you could have made a custom ContentDialog instead of putting it inside the user control, you can probably achieve your goal like this:
In your PopUpCustomDialogueUserControl class define a method that would show your popup:
public async Task ShowMyDialog() => await MyContentDialogCustom.ShowAsync();
Once you have it, add your PopUpCustomDialogueUserControl somwhere in your Page in xaml (remember to have a suitable namespace added (ContentDialogueBox) defined below as local) and add it a Name:
<local:PopUpCustomDialogueUserControl x:Name="MyCustomDialog"/>
Then you can call its method in code:
private async void ButtonShowContentDialog4_Click(object sender, RoutedEventArgs e)
{
await MyCustomDialog.ShowMyDialog();
}

Detect click outside control

I display TestControl in grid when user clicks on the button:
<Grid>
<myControls:TestControl Panel.ZIndex="2" Visibility="Collapsed" Width="100" Height="100" />
<Button "Open Test Control" Click="btnOpen_Click" />
</Grid>
How can I hide TestControl when user clicks outside this control?
You could handle the PreviewMouseLeftButtonDown event for the Grid:
<Grid Background="Transparent" PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<myControls:TestControl x:Name="tc" Visibility="Collapsed" Width="100" Height="100" />
<Button Content="Open Test Control" Click="btnOpen_Click" Grid.Row="1" />
</Grid>
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!tc.IsMouseOver)
tc.Visibility = Visibility.Collapsed;
}
Haven't tried it, but LostFocus event may be a way to go, given that you set focus to your test control after showing it.

WPF Popup as a separate control written in xaml

Is there chance to create a WPF Popup as a separate control, so it is not inside a window or user control?
I have a popup written in XAML:
<Popup PopupAnimation="Fade" Name="MyPopup" MinWidth="200" MinHeight="100" Width="200" Height="100" Placement="Center" VerticalAlignment="Center" HorizontalAlignment="Center" IsEnabled="True" IsOpen="False">
<Grid Width="Auto" Height="Auto" Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderThickness="2" CornerRadius="8" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2">
<Border.BorderBrush>
<SolidColorBrush Color="Gray"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="White"/>
</Border.Background>
</Border>
<StackPanel Grid.Row="0">
<Label Foreground="Blue" Content="Popup_Title"/>
</StackPanel>
<GroupBox Grid.Row="1" Header="Popup example content">
<StackPanel>
</StackPanel>
</GroupBox>
</Grid>
</Popup>
Now, on button click of my other control, I would like to do something like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
PopupControl p = new PopupControl();
p.IsOpen = true;
}
By looking at the example of UserControl or Window, I understand that I need to connect this popup with the actual c# class, something like:
public partial class PopupControl : Popup
{
public PopupControl()
{
InitializeComponent();
}
}
and then inside the Popup's XAML add class:
x:Class="WpfApplication1.PopupControl".
but two things:
1) There is no such a thing as x:Class for PopUp
2) Deriving from Popup won't have InitializeComponent(); method.
You almost got it right. While copy-pasting your Popup code in its own XAML file, you didn't add the necessary x namespace that contains the attached property x:Class:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
As soon as you add this to your root element (Popup), you can add x:Class="WpfApplication1.PopupControl". This will lead to the generation of a partial class in your obj folder that contains the InitializeComponent method that you were missing.
The easiest way to do that is by
creating a new UserControl from the "Add Item" dialog.
Then, rename the root element from UserControl to Popup.
Finally, from the code behind class, just remove : UserControl.

WPF button click and command doesn't work together MVVM

I'm developing some wpf application, using mvvm. I'm trying to use button click event and command together but command never get executed. Also when I use only command without click event it works perfect. Here is the code:
<ControlTemplate x:Key="reminderDataTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="150" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="New reminder:" HorizontalAlignment="Left" />
<TextBox Text="{Binding Path=ReminderText, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Height="150" Width="200" HorizontalAlignment="Left"/>
<Button Name="btnSaveReminder" Grid.Row="2" Content="Save" Width="auto" Height="20" HorizontalAlignment="Left" Click="btnSaveReminder_Click" Command="{Binding Path= btnSaveReminder}" />
</Grid>
</ControlTemplate>
Why is this happening?
Just to mention that I must use click and command together becouse my view and viewmodel are in different projects.
UPDATE:
Also to say that, when I use click and command together in buttons outside of control template, everything works perfect.
on the Click event, execute command.
private void btnClick(object sender, RoutedEventArgs e)
{
var btn = sender as Button;
btn.Command.Execute(btn.CommandParameter);
}

Binding Button to its handler by convention doesn't work

I have a WPF application with caliburn.micro. There is a user control MyView in a tab item of a tab control. Within that user control, there is another tab control. In one of its tabs, I added a button, and a corresponding method with the same name in the MyViewModel. But this method is not called when I click the button. Could you please tell what might cause it?
Thanks.
In the View:
<TabControl SelectedIndex="{Binding SelectedTabIndex}">
...
<TabItem x:Name="TextTab" Header="Text">
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
...
</ScrollViewer>
<Button Grid.Row="1" x:Name="SaveText" Content="Save" Width="50" Height="25" />
</Grid>
</TabItem>
In the ViewModel:
public void SaveText()
{
...
}
I found a solution:
<Button Grid.Row="1" x:Name="SaveText" cal:Message.Attach="SaveText" Content="Save" Width="50" Height="25" />
Still don't know why the convention didn't work without "Attach".

Categories

Resources