I have a rectangle textbox in WPF and there is already a button inside the textbox which is clickable. I need to make the entire rectangle textbox clickable, so users can click anywhere in the textbox rather than just the button to interact.
Is it possible to do so?
Here is my XAML:
<Grid Background="{StaticResource TinyGrayBrush}" Height="260" Width="530" Margin="10,10,10,10" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120*"/>
<ColumnDefinition Width="140*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Image x:Name="imgCard" Source="{StaticResource Exception-NoImageAvailable}" Stretch="Fill" />
<Image x:Name="hotpickEn" Source="{StaticResource HotPickEn}" Height="20" Width="70" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,30,0,0" Visibility="Hidden" />
<Image x:Name="hotpickCh" Source="{StaticResource HotPickCH}" Height="20" Width="70" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,30,0,0" Visibility="Hidden" />
</Grid>
<Grid x:Name="gdEnglish" Visibility="Visible" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="12*"/>
<RowDefinition Height="62*"/>
<RowDefinition Height="90*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="55*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="25,5,25,5"/>
</Style>
</Grid.Resources>
<TextBlock Grid.Row="1" x:Name="txtTitle" Text="SPARKLING SUNDAY BRUNCH BUFFET" FontSize="20" TextWrapping="Wrap" FontWeight="Medium" Foreground="{StaticResource SemiDarkGrayBrush}" Margin="5,0,5,6.5" />
<TextBlock Grid.Row="2" x:Name="txtDesc" Text="Pop your Sunday Morning with luxury sparkling bubble" FontSize="16" TextWrapping="Wrap" Foreground="{StaticResource GrayBrush}" Margin="5,3.5,5,6.5" />
<TextBlock Grid.Row="3" x:Name="txtPoint" Text="138,900 GP" FontSize="21" TextWrapping="Wrap" FontWeight="Medium" Foreground="{StaticResource GrayBrush}" Margin="25,3.5,25,6" />
<Button Grid.Row="4" x:Name="btnFindOutMore" Content="FIND OUT MORE OR REDEEM" Style="{StaticResource SmallWhiteRedButton}" Margin="12,0,12,0" FontSize="20" />
</Grid>
<Grid x:Name="gdChinese" Visibility="Hidden" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="12*"/>
<RowDefinition Height="62*"/>
<RowDefinition Height="90*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="55*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="25,5,25,5"/>
</Style>
</Grid.Resources>
<TextBlock Grid.Row="1" x:Name="txtCHTitle" Text="SPARKLING SUNDAY BRUNCH BUFFET" FontSize="20" TextWrapping="Wrap" FontWeight="Medium" Foreground="{StaticResource SemiDarkGrayBrush}" HorizontalAlignment="Left" Margin="5,4.667,0,5.333" />
<TextBlock Grid.Row="2" x:Name="txtCHDesc" Text="Pop your Sunday Morning with luxury sparkling bubble" FontSize="16" TextWrapping="Wrap" Foreground="{StaticResource GrayBrush}" HorizontalAlignment="Left" Margin="5,4.667,0,5.667" />
<TextBlock Grid.Row="3" x:Name="txtCHPoint" Text="138,900 GP" FontSize="21" TextWrapping="Wrap" FontWeight="Medium" Foreground="{StaticResource GrayBrush}" HorizontalAlignment="Left" Margin="25,3.5,25,6" Width="105" />
<Button x:Name="btnCHFindOutMore" Grid.Row="4" Content="FIND OUT MORE OR REDEEM" Style="{StaticResource SmallWhiteRedButton}" Margin="15,0,10,0"/>
</Grid>
As you are using Code-Behind for this:
You basically subscribe to the events of the Grid too
gdEnglish.TouchDown += gdEnglish_TouchDown;
gdEnglish.TouchUp += gdEnglish_TouchUp;
gdEnglish.TouchLeave += gdEnglish_TouchLeave;
gdEnglish.MouseDown += gdEnglish_MouseDown;
gdEnglish.MouseUp += gdEnglish_MouseUp;
gdEnglish.MouseLeave += gdEnglish_MouseLeave;
add a new private variable to indicate the current state
private bool gdEnglish_clickflag = false;
and create the different event handlers
private void gdEnglish_MouseLeave(object sender, MouseEventArgs e)
{
gdEnglish_clickflag = false;
}
private void gdEnglish_MouseUp(object sender, MouseButtonEventArgs e)
{
if (gdEnglish_clickflag)
{
gdEnglish_clickflag = false;
e.Handled = true;
//////////
// YOUR //
// CODE //
//////////
}
}
private void gdEnglish_MouseDown(object sender, MouseButtonEventArgs e)
{
gdEnglish_clickflag = true;
}
private void gdEnglish_TouchLeave(object sender, TouchEventArgs e)
{
gdEnglish_clickflag = false;
}
private void gdEnglish_TouchUp(object sender, TouchEventArgs e)
{
if (gdEnglish_clickflag)
{
gdEnglish_clickflag = false;
e.Handled = true;
//////////
// YOUR //
// CODE //
//////////
}
}
private void gdEnglish_TouchDown(object sender, TouchEventArgs e)
{
gdEnglish_clickflag = true;
}
I still want to recommend that you research the topic MVVM with WPF
it will make things like this more clean and easy
Related
So I have an audio in WAV format https://youtu.be/nunJDdIlnnk but for some reason, I cannot get it to paste all the transcription in the Textbox, However in the method SpeechRecognizer_Recognizing I can see on my debug windows, that everything is being recognized as the woman speaks.
var config = SpeechConfig.FromSubscription(KEY, Region);
MessageBox.Show("Ready to use speech service in " + config.Region);
// Configure voice
config.SpeechSynthesisVoiceName = "en-US-AriaNeural";
// Configure speech recognition
var taskCompleteionSource = new TaskCompletionSource<int>();
using var audioConfig = AudioConfig.FromWavFileInput(FilePath);
using var speechRecognizer = new SpeechRecognizer(config, audioConfig);
speechRecognizer.Recognizing += SpeechRecognizer_Recognizing;
speechRecognizer.Recognized += SpeechRecognizer_Recognized;
speechRecognizer.SessionStarted += SpeechRecognizer_SessionStarted;
speechRecognizer.SessionStopped += SpeechRecognizer_SessionStopped;
await speechRecognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);
// Waits for completion.
// Use Task.WaitAny to keep the task rooted.
Task.WaitAny(new[] { taskCompleteionSource.Task });
await speechRecognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
}
private void SpeechRecognizer_SessionStopped(object? sender, SessionEventArgs e)
{
Debug.WriteLine("Stopped");
}
private void SpeechRecognizer_SessionStarted(object? sender, SessionEventArgs e)
{
Debug.WriteLine("Started");
}
private void SpeechRecognizer_Recognized(object? sender, SpeechRecognitionEventArgs e)
{
var transcriptionStringBuilder = new StringBuilder();
if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
transcriptionStringBuilder.Append(e.Result.Text);
Text = transcriptionStringBuilder.ToString(); // This will be the text, that is displayed on textbox
IsVisible = Visibility.Visible;
}
}
private void SpeechRecognizer_Recognizing(object? sender, SpeechRecognitionEventArgs e)
{
Debug.WriteLine("Recogizing: " + e.Result.Text);
}
Output window
This is my XAML code for the UI
<Border Background="#272537"
CornerRadius="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Transcribe Me"
Foreground="White"
Margin="10,0,0,0"
FontSize="23"
VerticalAlignment="Center" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<syncfusion:SfHubTile Background="#FF1FAEFF">
<behaviors:Interaction.Triggers>
<behaviors:EventTrigger EventName="Click">
<behaviors:InvokeCommandAction Command="{Binding AzureCommand}"
CommandParameter="Audio" />
</behaviors:EventTrigger>
</behaviors:Interaction.Triggers>
<iconPacks:PackIconMaterial Kind="Music" Width="120"
Height="120"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="White" />
</syncfusion:SfHubTile>
<syncfusion:SfHubTile Grid.Column="1">
<syncfusion:SfHubTile.Header>
<TextBlock Text="Document"
Foreground="White"
FontSize="18"
FontStyle="Oblique" />
</syncfusion:SfHubTile.Header>
<syncfusion:SfHubTile.Title>
<TextBlock Text="Translate"
Foreground="White"
FontSize="18"
HorizontalAlignment="Center"
FontStyle="Oblique" />
</syncfusion:SfHubTile.Title>
<behaviors:Interaction.Triggers>
<behaviors:EventTrigger EventName="Click">
<behaviors:InvokeCommandAction Command="{Binding AzureCommand}"
PassEventArgsToCommand="True"
CommandParameter="Document" />
</behaviors:EventTrigger>
</behaviors:Interaction.Triggers>
</syncfusion:SfHubTile>
<TextBox Grid.Row="1"
IsReadOnly="True"
TextWrapping="Wrap"
Visibility="{Binding IsVisible}"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
AcceptsReturn="True"
Grid.ColumnSpan="2"
Margin="10" />
<Button Grid.Column="1"
Grid.Row="2"
Visibility="{Binding IsVisible}"
Content="Copy"
Command="{Binding CopyCommand}"
Foreground="White"
FontWeight="Black"
VerticalAlignment="Center"
Margin="0,0,10,10">
</Button>
</Grid>
</Grid>
</Border>
When I run the code, my text box only has the last part of the of the video, witch is "Do I look alright"
The problem was, that I was puttingin my textbox every single sentence that she said.
What you have to do, is to capture everything in the STOPPED method, and probably use a list of chars, loop thru every char, and crate a stringbulder, because using str += item, will create a string every time and is less efficient.
SUMMARY OF THE PROBLEM:
I have main window which has a frame and a button, in the frame i'm going to show one user control at a time (i provided an image of my usercontrol).
in the first UserControl, i will write 4 player names (two for each team).
after i press the button and i go to next usercontrol i want to show the names of the players in textblock. I also want to bind IsChecked property of radio button in first UserControl to the second UserControl. (i have other buttons that show up in mainWindow depends on what usercontrol is in the Frame right Now)
WHAT I TRIED:
I tried binding the textbox property to the textblock in the second usercontrol but it doesnt show or i cant access it.
because i have the button in the mainWindow i tried saving the names in variable then pass it to next usercontrol but didnt work also.
Also tried alot of random online solution i found online but nothing worked.
i need a way to expose the property of First UserControl to be used in the Second UserControl
MY CODE
MainWindow xaml
<Grid SnapsToDevicePixels="True" x:Name="myGrid" >
<Grid.Background>
<ImageBrush x:Name="myBackground" ImageSource="background1.png" Stretch="UniformToFill"/>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
<RowDefinition Height=" auto" />
<RowDefinition Height=" 20" />
</Grid.RowDefinitions>
<Frame x:Name="Main" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="5" NavigationUIVisibility="Hidden" >
</Frame>
<Button Style="{StaticResource StandardButton}" Visibility="Visible" x:Name="playersBtn" Grid.Column="2" Grid.Row ="2" Margin="100,40,100,40" FontSize="36" Content="إبدأ" FontFamily="Ara Hamah Homs" Padding="50,0" Background="#FFFFE900" Click="playerInfoBtn" BorderBrush="{x:Null}" Foreground="Black" >
</Button>
MainWindow c#
namespace Try3
{
public partial class MainWindow : Window
{
SoundPlayer MP = new SoundPlayer();
public MainWindow()
{
InitializeComponent();
MP.SoundLocation = "C:/Users/eadh2/Desktop/game tries/try3/try3/sound1.wav";
MP.PlayLooping();
}
private void playerInfoBtn(object sender, RoutedEventArgs e)
{
Main.Content = new PlayersInfoPage();
playersBtn.Visibility = Visibility.Hidden;
startBtn.Visibility = Visibility.Visible;
icon.Visibility = Visibility.Collapsed;
ImageBrush b = new ImageBrush();
b.ImageSource = new BitmapImage(new Uri("pack://application:,,,/background flat.png"));
myGrid.Background = b;
}
private void startBtn_Click(object sender, RoutedEventArgs e)
{
Main.Content = new gamePage();
startBtn.Visibility = Visibility.Collapsed;
gamePageBoarder.Visibility = Visibility.Visible;
}
private void startBtn_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
startBtn.Background = Brushes.DarkGreen;
}
}
}
First usercontrol xaml to enter player names (Image of First UserControl to enter player names)
<UserControl x:Class="Try3.PlayersInfoPage"
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:Try3"
mc:Ignorable="d"
d:DesignHeight="862.179" d:DesignWidth="1210.632" >
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions >
<ColumnDefinition Width="150" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width=" *" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="AUTO" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height=" *" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Text="بيانات الفريق الأحمر" FontSize="36" Margin="50,0,50,0" FontFamily="Ara Hamah Homs" />
<TextBox x:Name="redFirst" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,30,0,20" Padding="10" FontSize="36" HorizontalContentAlignment="Center" Text="اللاعب الأول" Foreground="#FF919191" GotMouseCapture="redFirst_GotMouseCapture" FontFamily="Ara Hamah Homs" />
<TextBox x:Name="redSecond" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,30,0,110" Padding="10" FontSize="36" HorizontalContentAlignment="Center" Text="اللاعب الثاني" Foreground="#FF919191" GotMouseCapture="redSecond_GotMouseCapture1" FontFamily="Ara Hamah Homs" />
<TextBlock Grid.Column="4" Grid.Row="1" Grid.ColumnSpan="2" Text="بيانات الفريق الأخضر " FontSize="36" Margin="50,0,50,20" FontFamily="Ara Hamah Homs" />
<TextBox x:Name="greenFirst" Grid.Row="2" Grid.Column="4" Grid.ColumnSpan="2" Margin="0,30,0,20" Padding="10" FontSize="36" HorizontalContentAlignment="Center" Text="اللاعب الأول" Foreground="#FF919191" GotMouseCapture="greenFirst_GotMouseCapture2" FontFamily="Ara Hamah Homs" />
<TextBox x:Name="greenSecond" Grid.Row="3" Grid.Column="4" Grid.ColumnSpan="2" Margin="0,30,0,110" Padding="10" FontSize="36" HorizontalContentAlignment="Center" Text="اللاعب الثاني" Foreground="#FF919191" GotMouseCapture="greenSecond_GotMouseCapture3" FontFamily="Ara Hamah Homs" />
<Border x:Name="roundsBoarder" Grid.Column="3" Grid.Row="2" Grid.RowSpan="2" BorderThickness ="3" BorderBrush="Black" CornerRadius="0" Margin="20,50,20,130" MaxHeight="170" MaxWidth="350" VerticalAlignment="Center" Background="#99FFFFFF" MouseEnter="Border_MouseEnter" MouseLeave="roundsBoarder_MouseLeave">
<StackPanel HorizontalAlignment="Center" >
<StackPanel Orientation="Horizontal" >
<Viewbox Height="40" Width="40" >
<RadioButton BorderBrush="#FFFFE900" VerticalContentAlignment="Center" HorizontalAlignment="Left" GroupName="roundsNumber" FontFamily="Ara Hamah Homs" FontSize="12"/>
</Viewbox>
<TextBlock Text="جولة" FontSize="42" Margin="20,0,0,0" FontFamily="Alnaqaaa R" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
<Viewbox Height="40" Width="40" >
<RadioButton BorderBrush="#FFFFE900" VerticalContentAlignment="Center" HorizontalAlignment="Left" GroupName="roundsNumber" FontFamily="Ara Hamah Homs" FontSize="12"/>
</Viewbox>
<TextBlock Text="ثلاث جولات" FontSize="42" Margin="20,0,0,0" FontFamily="Alnaqaaa R" />
</StackPanel>
</StackPanel>
</Border>
</Grid>
First UserControl C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Try3
{
public partial class PlayersInfoPage : UserControl
{
public PlayersInfoPage()
{
InitializeComponent();
}
private void redFirst_GotMouseCapture(object sender, MouseEventArgs e)
{
redFirst.Text = "";
redFirst.Foreground = Brushes.Black;
}
private void redSecond_GotMouseCapture1(object sender, MouseEventArgs e)
{
redSecond.Text = "";
redSecond.Foreground = Brushes.Black;
}
private void greenFirst_GotMouseCapture2(object sender, MouseEventArgs e)
{
greenFirst.Text = "";
greenFirst.Foreground = Brushes.Black;
}
private void greenSecond_GotMouseCapture3(object sender, MouseEventArgs e)
{
greenSecond.Text = "";
greenSecond.Foreground = Brushes.Black;
}
private void Save_MouseEnter(object sender, MouseEventArgs e)
{
}
private void Save_MouseLeave(object sender, MouseEventArgs e)
{
}
private void Border_MouseEnter(object sender, MouseEventArgs e)
{
roundsBoarder.Background = new SolidColorBrush(Colors.White) { Opacity = 1 };
roundsBoarder.CornerRadius = new CornerRadius(20);
}
private void roundsBoarder_MouseLeave(object sender, MouseEventArgs e)
{
roundsBoarder.Background = new SolidColorBrush(Colors.White) { Opacity = 0.6 };
roundsBoarder.CornerRadius = new CornerRadius(0);
}
}
}
Second UserControl xaml to show player names in each side
<UserControl x:Class="Try3.gamePage"
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:try3"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="50" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions >
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
<RowDefinition Height="50" />
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" >
<TextBlock HorizontalAlignment="Center" FontSize="36" FontFamily="Ara Hamah Homs" Text="الفريق الأحمر" />
<TextBlock x:Name="redFirstPlayer" FontSize="24" FontFamily="Ara Hamah Homs" Text="اللاعب الاول" HorizontalAlignment="Center"/>
<TextBlock x:Name="redSecondPlayer" FontSize="24" FontFamily="Ara Hamah Homs" Text="اللاعب الثاني" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="6" Grid.ColumnSpan="2" Grid.Row="1">
<TextBlock FontSize="36" FontFamily="Ara Hamah Homs" Text="الفريق الأخضر" HorizontalAlignment="Center" Margin="0,0,0,20"/>
<TextBlock x:Name="greenFirstPlayer" FontSize="24" FontFamily="Ara Hamah Homs" Text="اللاعب الاول" HorizontalAlignment="Center"/>
<TextBlock x:Name="greenSecondPlayer" FontSize="24" FontFamily="Ara Hamah Homs" Text="اللاعب الثاني" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock x:Name="redScore" Grid.Column="1" Grid.Row="3" FontSize="42" FontFamily="Ara Hamah Homs" Text="0" HorizontalAlignment="center" />
<Image Source="trophy (1).png" Grid.Column="2" Grid.Row="3" HorizontalAlignment="Left"/>
<TextBlock x:Name="greenScore" Grid.Column="7" Grid.Row="3" FontSize="42" FontFamily="Ara Hamah Homs" HorizontalAlignment="center" Text="0" />
<Image Source="trophy (1).png" Grid.Column="6" Grid.Row="3" HorizontalAlignment="Right"/>
<StackPanel Grid.Row="1" Grid.Column="6" Grid.ColumnSpan="2" Margin="0,50,0,0" >
</StackPanel>
</Grid>
I want to have a Page object, that contains Frames, that contain another Page. The current result looks like that:
But I want the Page to be appear in all of the Frames.
How can I achieve that?
The page that contains Frames:
public partial class CombinedPage : Page
{
public CombinedPage()
{
InitializeComponent();
Frame1.Content = MainWindow.testPage;
Frame2.Content = MainWindow.testPage;
Frame3.Content = MainWindow.testPage;
Frame4.Content = MainWindow.testPage;
}
}
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="5" Background="Black"
VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="5" Background="Black"
VerticalAlignment="Center" HorizontalAlignment="Stretch" />
<Frame NavigationUIVisibility="Hidden" x:Name="Frame1" Grid.Row="0" Grid.Column="0"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame2" Grid.Row="0" Grid.Column="2"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame3" Grid.Row="2" Grid.Column="0"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame4" Grid.Row="2" Grid.Column="2"/>
</Grid>
The TestPage XAML:
<Grid>
<Viewbox Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Label Name="LiveTimeLabel" Content="%TIME%" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" Foreground="#cccccc" VerticalAlignment="Stretch" FontWeight="Bold" />
</Viewbox>
</Grid>
Thanks for any advice!
EDIT 1: Ok, then if I can use Page object only once, then how change it's location from one frame to another? I tried this, but it doesn't seem to be work:
public partial class CombinedPage : Page
{
public CombinedPage()
{
InitializeComponent();
Frame1.Content = MainWindow.testPage;
Frame2.Content = MainWindow.testPage;
Frame3.Content = MainWindow.testPage;
Frame4.Content = MainWindow.testPage;
}
private void butt1_Click(object sender, System.Windows.RoutedEventArgs e)
{
Frame1.Content = MainWindow.testPage;
}
private void butt2_Click(object sender, System.Windows.RoutedEventArgs e)
{
Frame2.Content = MainWindow.testPage;
}
private void butt3_Click(object sender, System.Windows.RoutedEventArgs e)
{
Frame3.Content = MainWindow.testPage;
}
private void butt4_Click(object sender, System.Windows.RoutedEventArgs e)
{
Frame4.Content = MainWindow.testPage;
}
}
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="5" Background="Black"
VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="5" Background="Black"
VerticalAlignment="Center" HorizontalAlignment="Stretch" />
<Frame NavigationUIVisibility="Hidden" x:Name="Frame1" Grid.Row="0" Grid.Column="0"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame2" Grid.Row="0" Grid.Column="2"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame3" Grid.Row="2" Grid.Column="0"/>
<Frame NavigationUIVisibility="Hidden" x:Name="Frame4" Grid.Row="2" Grid.Column="2"/>
<StackPanel Grid.Row="3" Grid.Column="0" Orientation="Horizontal">
<Button x:Name="butt1" Width="50" Click="butt1_Click"/>
<Button x:Name="butt2" Width="50" Click="butt2_Click"/>
<Button x:Name="butt3" Width="50" Click="butt3_Click"/>
<Button x:Name="butt4" Width="50" Click="butt4_Click"/>
</StackPanel>
</Grid>
You should create separate instance of the same Page class:
public CombinedPage()
{
InitializeComponent();
Frame1.Content = new TestPage();
Frame2.Content = new TestPage();
Frame3.Content = new TestPage();
Frame4.Content = new TestPage();
}
A single instance of a control can only appear once in the visual tree so you cannot display the same page instance in more than one Frame.
I'm creating a WPF program for editing PowerPoint presentation using Syncfusion library but whenever I run the program I see the memory increase when navigating from a page to another. I'm using WPF Application with a window that navigates between multiple pages.
How to encounter this problem actually?
Thank you.
These photos show where the leak is located :
PS: Please focus on the InitializeNonUITasks method in home.cs because that's where the leak is.
Home Page XAML:
<Page x:Class="ProjectSABX.Pages.Home"
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:ProjectSABX.Pages"
xmlns:syncfusion="clr-namespace:Syncfusion.Windows;assembly=Syncfusion.Shared.Wpf"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Width="1175" Height="660" KeyDown="Window_KeyDown"
Title="Home">
<Grid ShowGridLines="False" Margin="2,-2,-2,2">
<Grid Grid.Row="0" ShowGridLines="False">
<Grid.Background>
<SolidColorBrush Color="White" Opacity="0.5" />
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="2.5*"></RowDefinition>
</Grid.RowDefinitions>
<Rectangle Height="52" Grid.Row="0" VerticalAlignment="Top" Fill="#FF80A20D"></Rectangle>
<TextBlock Name="titleBarTextBlock" Text="Aperçu" Height="40" Foreground="White" FontFamily="Segoe UI" FontWeight="Normal" Padding="15" FontSize="17.75" VerticalAlignment="Top" Grid.Row="0" HorizontalAlignment="Center"></TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 15 10 0" Grid.Column="3" Grid.Row="0">
</StackPanel>
<Image Source="/Images/ViewerIcons/ppt__logo for header.png" Grid.Column="0" HorizontalAlignment="Left" Margin="15" VerticalAlignment="Top" Height="30"></Image>
</Grid>
<Grid Grid.Row="1" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="0*" />
<RowDefinition Height="445*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="59*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="8*" />
</Grid.ColumnDefinitions>
<Border ClipToBounds="True" BorderBrush="Black" BorderThickness=".7" Grid.Row="1" Grid.Column="0" Grid.RowSpan ="3" Margin="0,51,3,0">
<ScrollViewer Name="scrollViewer" Focusable="False" CanContentScroll="False" BorderBrush="Black" BorderThickness="1" HorizontalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="0" Grid.RowSpan ="3">
<Grid ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="9*" />
</Grid.ColumnDefinitions>
<StackPanel Name="stackpanel" Grid.Column="1" Width="170" />
</Grid>
</ScrollViewer>
</Border>
<Image Name ="centerSlideImage" Grid.Row="1" Grid.Column="1" Margin="0,57,5,19" />
<Canvas Name="loadingIndicatorCanvas" Visibility="Collapsed" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" Margin="-250,-100,0,0">
<Canvas Canvas.Left="21.75" Canvas.Top="14" Height="81.302" Width="80.197">
<Canvas.Resources>
<Style TargetType="Ellipse">
<Setter Property="Width" Value="5" />
<Setter Property="Height" Value="5" />
<Setter Property="Fill" Value="#FF9BD226" />
</Style>
</Canvas.Resources>
<Ellipse x:Name="_00" Canvas.Left="24.75" Canvas.Top="50" />
<Ellipse x:Name="_01" Canvas.Top="36" Canvas.Left="29.5" />
<Ellipse x:Name="_02" Canvas.Left="43.5" Canvas.Top="29.75" />
<Ellipse x:Name="_03" Canvas.Left="57.75" Canvas.Top="35.75" />
<Ellipse x:Name="_04" Canvas.Left="63.5" Canvas.Top="49.75" />
<Ellipse x:Name="_05" Canvas.Left="57.75" Canvas.Top="63.5" />
<Ellipse x:Name="_06" Canvas.Left="43.75" Canvas.Top="68.75" />
<Ellipse x:Name="_07" Canvas.Top="63.25" Canvas.Left="30" />
<Ellipse Stroke="{x:Null}" Width="39.5" Height="39.5" Canvas.Left="31.75" Canvas.Top="37" Fill="{x:Null}" />
</Canvas>
</Canvas>
<Grid Grid.Row="3" Grid.Column="1" ShowGridLines="False" Margin="0, -10">
<Grid.RowDefinitions>
<RowDefinition Height="0.5*" />
<RowDefinition Height="20*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="42*" />
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="44*" />
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="238*" />
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="40*" />
<ColumnDefinition Width="46*" />
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="45*" />
</Grid.ColumnDefinitions>
<Image Name="openDocument" Grid.Row="1" Grid.Column="1" Height="30" Width="30" Source="/Images/ViewerIcons/ppt__open.png" MouseDown="openDocument_MouseDown" MouseEnter="openDocument_MouseEnter" MouseLeave="openDocument_MouseLeave" Margin="0,5,7,4"></Image>
<Image Name="createPdfDocument" Grid.Row="1" Grid.Column="3" Height="30" Width="30" Source="/Images/ViewerIcons/ppt_pdf.png" MouseDown="createPdfDocument_MouseDown" MouseEnter="createPdfDocument_MouseEnter" MouseLeave="createPdfDocument_MouseLeave" Margin="0,5,8,4"></Image>
<DockPanel Grid.Row="1" Grid.Column="6" Grid.ColumnSpan="3">
<Image Name="prevDocument" Height="30" Width="30" Source="/Images/ViewerIcons/ppt__back.png" MouseDown="prevDocument_MouseDown" MouseEnter="prevDocument_MouseEnter" MouseLeave="prevDocument_MouseLeave"></Image>
<Label Name="lblPageDisplay" Height="30" MinWidth="30" FontFamily="Segoe UI" FontWeight="Bold" FontSize="18" VerticalAlignment="Center" VerticalContentAlignment="Center" Padding="35,0,0,0" Foreground="#646464" />
<Image Name="NextDocumentIconImage" Height="30" Width="30" Source="/Images/ViewerIcons/ppt__for.png" MouseDown="NextDocument_MouseDown" MouseEnter="NextDocument_MouseEnter" MouseLeave="NextDocument_MouseLeave" Margin="-10,0"></Image>
</DockPanel>
</Grid>
</Grid>
</Grid>
Home Page C#:
public Home()
{
InitializeComponent();
pdfBackroundWorker.DoWork += pdfBackroundWorker_DoWork;
pdfBackroundWorker.RunWorkerCompleted += pdfBackroundWorker_RunWorkerCompleted;
this.Background = new SolidColorBrush(Color.FromRgb(244, 244, 244));
filePath = "/Data/Template.pptx";
InitializeNonUITasks();
InitializeUITasks(filePath);
}
private void openDocument_MouseDown(object sender, MouseButtonEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "PowerPoint Presentations|*.pptx";
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
string filename = dlg.FileName;
filePath = filename;
slideNumber = 1;
displayBackroundWorker.RunWorkerAsync();
}
}
private void InitializeNonUITasks()
{
try
{
presentation = Presentation.Open(filePath);
}
catch (Exception exp)
{
MessageBox.Show("This PowerPoint Presentation cannot be opened properly, please contact support");
return;
}
slideImageSources.Clear();
thumbnailImageSource.Clear();
printImages.Clear();
currentSlideNumber = 0;
presentation.ChartToImageConverter = new ChartToImageConverter();
presentation.ChartToImageConverter.ScalingMode = Syncfusion.OfficeChart.ScalingMode.Best;
try
{
foreach (ISlide slide in presentation.Slides)
{
using (System.Drawing.Image image = slide.ConvertToImage(Syncfusion.Drawing.ImageType.Bitmap))
{
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
printImages.Add(image.Clone() as System.Drawing.Image);
System.Drawing.Image newImage = image.GetThumbnailImage(170, 100, myCallback, System.IntPtr.Zero);
using (Stream ms = new MemoryStream())
{
newImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
thumbnailImageSource.Add(decoder.Frames[0]);
}
using (Stream ms = new MemoryStream())
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
slideImageSources.Add(decoder.Frames[0]);
}
}
}
}
catch (Exception)
{
MessageBox.Show("This PowerPoint Presentation cannot be converted to images properly, please contact support");
return;
}
}
MainWindow XAML:
<Frame Grid.Column="1" Grid.Row="1" NavigationUIVisibility="Hidden" x:Name="Main" Source="./Pages/Home.xaml">
<Frame.Background>
<SolidColorBrush Color="#FFB0B0B0" Opacity="0.49" />
</Frame.Background>
</Frame>
MainWindow.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = this;
InitializeComponent();
}
private void ButtonClickHomePage(object sender, RoutedEventArgs e)
{
Main.Content = new Home();
}
}
Edit1: I tried to use the dispose() method for each object that implemented IDisposable, When navigating at first, the memory process decreases. then when I navigate from page to page it increases again.
It is hard to pinpoint the issue like this, but I do have some suggestions:
Usually it's about calling Dispose on all objects that implement the IDisposable interface.
check all object for the IDisposable interface and call Dispose() if it's available. E.g.: newImage.Dispose() (or use using)
Also, all the disposable objects in the lists printImages, thumbnailImageSource etc, should be disposed as well.
Also, I believe the decoder should be disposed as well, as well as the presentation, although I can be mistaken.
This will give you a good starting point - there might be more, but you should rule out and fix this first.
The loop is a likely suspect to be causing the memory increase.
Here's more info on IDisposable. Also, if you have implemented the IDisposable interface yourself - it's prety common to make a mistake with that as well. In that case you should double check it.
I am doing a project where I have to change button colors based on sliders in WPF. This is my XAML design.
XAML file
So, I have made 64 buttons, and I have tried implementing multiple options, and none worked for me.
I have this xaml code:
<Grid Grid.Column="0" Grid.RowSpan="4" Grid.ColumnSpan="4" HorizontalAlignment="Left" Height="790" Margin="0,10,0,0" Grid.Row="0" VerticalAlignment="Top" Width="800">
<Grid Margin="230,114,230,346" AutomationProperties.Name="ledMatrix" Tag="ledMatrix" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED00" Click="changeLedIndicatiorColor" x:Name="LEDButton"/>
<Button Grid.Column="1" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED01"/>
<Button Grid.Column="2" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED02"/>
<Button Grid.Column="3" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED03"/>
<Button Grid.Column="4" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED04"/>
<Button Grid.Column="5" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED05"/>
<Button Grid.Column="6" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED06"/>
<Button Grid.Column="7" Grid.Row="0" Height="40" Width="40" Command="{Binding LEDBtn}" Background="#FFAAAAAA" Tag="LED07"/>
and sliders:
<Grid Margin="230,480,230,170">
<Slider x:Name="SeekR" Margin="0,0,0,120" Tag="seekR" Maximum="255" Background="Red" ></Slider>
<Slider x:Name="SeekG" Margin="0,50,0,70" Tag="seekG" Maximum="255" Background="Green"></Slider>
<Slider x:Name="SeekB" Margin="0,100,0,20" Tag="seekB" Maximum="255" Background="Blue"></Slider>
</Grid>
I have tried placing this in my xaml.cs file :
public void changeColor()
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb); //Create object of Color class.
SolidColorBrush colorBrush = new SolidColorBrush(cc); //Creating object of SolidColorBruch class.
LEDButton.Background = colorBrush; //Setting background of stack panel.
}
private void changeLedIndicatiorColor(object sender, RoutedEventArgs e)
{
changeColor();
}
But from this code, I have to name all the buttons differently butI want to have the same binding for all buttons and try to connect it all together, so for example I would like to set color by sliders and when I click the button color would change. Then, I can change the color, and make other buttons that different color.
Refactor ChangeColor to accept a Button, the button to change the color for:
private void ChangeLedIndicatiorColor_OnClick(object sender, RoutedEventArgs e)
{
ChangeColor(sender as Button);
}
public void ChangeColor(Button button)
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb);
SolidColorBrush colorBrush = new SolidColorBrush(cc);
button.Background = colorBrush;
}
Then register the ChangeLedIndicatiorColor event handler for each Button.Click:
...
<Button Click="ChangeLedIndicatiorColor" />
<Button Click="ChangeLedIndicatiorColor" />
<Button Click="ChangeLedIndicatiorColor" />
...
You can use the EventSetter so that the event can be applicable to all the buttons. You don't need to attach the click event handler to each button anymore.
<Window.Resources>
<Style TargetType="Button">
<EventSetter Event="Click" Handler="ChangeLedIndicatiorColor"/>
</Style>
</Window.Resources>
And inside event handler you can change the color of the button which triggered the click event.
private void changeLedIndicatiorColor(object sender, RoutedEventArgs e)
{
byte rr = (byte)SeekR.Value;
byte gg = (byte)SeekG.Value;
byte bb = (byte)SeekB.Value;
Color cc = Color.FromRgb(rr, gg, bb);
SolidColorBrush colorBrush = new SolidColorBrush(cc);
(sender as Button).Background = colorBrush;
}