Getting and setting large amount of text data in clipboard - c#

I'm making simple tool app in C#, I have a textbox and I want to paste some text (around 300k lines), but this makes the app unresponsive. I waited like 10 minutes and nothing moved forward.
Is there some way to handle paste and copy operations on large data sets in smoother way? For example pasting and copying same amount of data in Windows Notepad takes just few seconds.
I use
Windows.ApplicationModel.DataTransfer.Clipboard.GetContent()
and at this app hangs.
Example Code
Xaml
<Window
x:Class="App2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" Grid.RowSpan="1">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" Grid.RowSpan="1" Margin="5" VerticalScrollBarVisibility="Visible" >
<TextBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="False" Header="Query Result" Text='{x:Bind pasteResult, Mode=TwoWay}' PlaceholderText="Paste results here" TextWrapping="Wrap"/>
</ScrollViewer>
</Grid>
</Window>
cs file
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace App2
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
public string pasteResult;
public MainWindow()
{
this.InitializeComponent();
}
}
}

As #Simon Mourier mentioned in the comments, the performance problem is not related to the clipboard, but the TextBox control processing that amount of data.
So, let me give you another option using the ItemsRepeater which comes with virtualization built-in. (In my laptop) it takes approx. 3 secs to show 500K lines of text from the clipboard.
MainWindow.xaml
<Window
x:Class="ClipboardTests.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"
mc:Ignorable="d">
<Grid RowDefinitions="Auto,*">
<StackPanel
Grid.Row="0"
Orientation="Horizontal">
<Button
Click="PasteButton_Click"
Content="Paste" />
<Button
Click="ClearButton_Click"
Content="Clear" />
<TextBlock
x:Name="MessageTextBox"
VerticalAlignment="Center" />
</StackPanel>
<ScrollViewer Grid.Row="1">
<ItemsRepeater x:Name="TextItemsRepeaterControl" />
</ScrollViewer>
</Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel.DataTransfer;
namespace ClipboardTests;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private static async Task<IEnumerable<string>> GetTextLinesFromClipboard()
{
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text) is true)
{
string text = await dataPackageView.GetTextAsync();
string[] lines = text
.ReplaceLineEndings()
.Split(Environment.NewLine, StringSplitOptions.None);
return lines;
}
return Enumerable.Empty<string>();
}
private async void PasteButton_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
IEnumerable<string> lines = await GetTextLinesFromClipboard();
this.TextItemsRepeaterControl.ItemsSource = lines;
stopwatch.Stop();
this.MessageTextBox.Text = $"Pasted {this.TextItemsRepeaterControl.ItemsSourceView.Count} items in {stopwatch.Elapsed.TotalSeconds} s.";
}
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
this.TextItemsRepeaterControl.ItemsSource = null;
}
}

Related

How to bind properties both ways WPF

I am a reeeally noob beginner WPF developer, and getting the hang of c#.
I am creating an app, where I need a knob Button and a TextBox Display, where the knob adjusts the text from the display, and the display, if text is changed, updates the knob position.
Inage example of my application
I've managed to create the Knob Button, which spins when clicked and dragged, and also managed to bind it's value to the TextBox, it displays the value perfectly, but I can't make the TextBox Text update the Knob's position, which is defined by Angle variable (from the RotateTransform thing), the code is as follows:
<UserControl x:Class="quaselaeuespero.VolumeControl"
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:quaselaeuespero"
mc:Ignorable="d"
d:DesignHeight="154" d:DesignWidth="148">
<Grid>
<Image Name="aPorradoknob" Source="Knob.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform Angle="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:VolumeControl}}, Path=Angle}"/>
</Image.RenderTransform>
</Image>
</Grid>
</UserControl>
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 quaselaeuespero
{
/// <summary>
/// Interaction logic for VolumeControl.xaml
/// </summary>
public partial class VolumeControl : UserControl
{
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(VolumeControl), new UIPropertyMetadata(0.0));
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
public VolumeControl()
{
InitializeComponent();
this.Angle = 120;
this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
this.MouseUp += new MouseButtonEventHandler(OnMouseUp);
this.MouseMove += new MouseEventHandler(OnMouseMove);
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(this);
}
private void OnMouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (Mouse.Captured == this)
{
// Get the current mouse position relative to the volume control
Point currentLocation = Mouse.GetPosition(this);
// We want to rotate around the center of the knob, not the top corner
Point knobCenter = new Point(this.ActualHeight / 2, this.ActualWidth / 2);
// Calculate an angle
double radians = Math.Atan((currentLocation.Y - knobCenter.Y) /
(currentLocation.X - knobCenter.X));
this.Angle = radians * 180 / Math.PI;
// Apply a 180 degree shift when X is negative so that we can rotate
// all of the way around
if (currentLocation.X - knobCenter.X < 0)
{
this.Angle += 180;
}
if(this.Angle >= -90 && this.Angle <= -45)
{
this.Angle = 270;
}
if (this.Angle >= -45 && this.Angle <= 0)
{
this.Angle = 1;
}
this.Angle = Math.Round(this.Angle, 1);
}
}
}
}
The Knob is <VolumeControl/> and Display is <DisplayBPM/>, in the main Window I tried to bind them both:
<Window x:Class="quaselaeuespero.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:quaselaeuespero"
mc:Ignorable="d"
Title="MainWindow" Height="540" Width="960">
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Background.png"/>
</Grid.Background>
<local:VolumeControl x:Name="Knobão" Margin="123,240,675,111" RenderTransformOrigin="0.5,0.5" Angle="{Binding ElementName=BPMDisplay, Path=BPM, UpdateSourceTrigger=Explicit}"/>
<local:DisplayBPM x:Name="BPMDisplay" BPM="{Binding ElementName=Knobão, Path=Angle, UpdateSourceTrigger=Explicit}" Margin="68,153,656,274" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Window>
The following is the code for DisplayBPM:
<UserControl x:Class="quaselaeuespero.DisplayBPM"
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:quaselaeuespero"
mc:Ignorable="d"
d:DesignHeight="79
" d:DesignWidth="229"
Name="Display">
<Grid Margin="0">
<TextBox x:Name="BPMTexto" Text="{Binding ElementName=Display, Path=BPM}" HorizontalAlignment="Right" Margin="0,0,4,0" Width="222" BorderBrush="{x:Null}" SelectionBrush="{x:Null}" Foreground="#FFCF1D1D" FontSize="80" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontFamily="DS-Digital" RenderTransformOrigin="0.5,0.5" CaretBrush="#FFCF1D1D">
<TextBox.Background>
<ImageBrush ImageSource="Display BPM.png" Stretch="Uniform"/>
</TextBox.Background>
</TextBox>
</Grid>
</UserControl>
and the DisplayBPM.xaml.cs:
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 quaselaeuespero
{
/// <summary>
/// Interaction logic for DisplayBPM.xaml
/// </summary>
public partial class DisplayBPM : UserControl
{
private void BPMTexto_TextChanged(object sender, EventArgs e)
{
BPM = Convert.ToDouble(BPMTexto.Text);
}
public static readonly DependencyProperty BPMProperty =
DependencyProperty.Register("BPM", typeof(double), typeof(DisplayBPM), new UIPropertyMetadata(0.0));
public double BPM
{
get { return (double)GetValue(BPMProperty); }
set { SetValue(BPMProperty, value); }
}
public DisplayBPM()
{
InitializeComponent();
BPM = 1;
}
}
}
The problem is that BPM (variable from DisplayBPM, from which TextBox gets its input) doesn't seem to be changed, and if it is changed, it is not changing Angle (variable from RotateTransform that determines the Knob position). Can anyone help me? I know there are probably tons of basic problems, it would really help me if you could explain them to me. Thank you so much!
To start, making a custom user control that has Dependency Properties is not the solution for every problem in WPF.
WPF Apps are primarily architected with MVVM: Model - View - ViewModel
With that stated for your specific need I would keep the VolumeControl as that is the correct way to create custom UserControls that have custom DependencyProperties
I would then delete the DisplayBPM class as it is not needed.
I would setup a ViewModel to interact between your controls that contains a single BPM string property.
Here is an example ViewModel I would use:
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _bpm;
public string BPM
{
get => _bpm;
set
{
_bpm = value;
RaisePropertyChanged(nameof(BPM));
}
}
public void RaisePropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
As a side note, I would suggest reading up on INotifyPropertyChanged
as there are many libraries out there that you can use to help with
WPF and MVVM
I would then setup the Window with the VolumeControl and just a TextBox to hold the BPM value. Both of these should have a {Binding BPM, Mode=TwoWay} so that you pass the BPM value between controls.
You can then decide on the TextBox binding if you want the value to take as the user is typing or after the user leaves the field (usually with the Tab key). To have the value update the VolumeControl as the user is typing have UpdateSourceTrigger=PropertyChanged in the binding.
See my example here:
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Background.png"/>
</Grid.Background>
<local:VolumeControl
x:Name="Knobão"
Margin="123,240,675,111"
RenderTransformOrigin="0.5,0.5"
Angle="{Binding BPM, Mode=TwoWay}" />
<TextBox
Text="{Binding BPM, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="68,153,656,274"
MinWidth="222"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBox.Background>
<ImageBrush
ImageSource="Display BPM.png"
Stretch="Uniform" />
</TextBox.Background>
</TextBox>
</Grid>
If you are not familiar with how ViewModels and DataContext work within WPF I would recommend reading up on that as that is the primary way to setup an MVVM architecture for WPF apps.

Looping through controls of different types and create stringbuilder for copy

I cannot find a similar question or answer to what I am asking but if there is one out there I do apologize. What I am looking to achieve is to simply loop through all my controls in a user control and then write to a string builder in the order of the loop.
The code below outlines a simple example and I did try some limited things based on me being knew to C# etc.
<Window x:Class="CopyandPaste.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:CopyandPaste"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="MainGrid">
<Button x:Name="CopyButton" Content="Copy Button" HorizontalAlignment="Left" Margin="10,34,0,0" VerticalAlignment="Top" RenderTransformOrigin="-4.265,-0.098" Height="41" Width="120" Click="CopyButton_Click"/>
<Grid x:Name="MasterGrid" HorizontalAlignment="Left" Height="378" Margin="146,10,0,0" VerticalAlignment="Top" Width="572">
<TextBox HorizontalAlignment="Center" Margin="0,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="408" Height="23" Grid.Column="1"/>
<RadioButton x:Name="RadioButton" Content="RadioButton" HorizontalAlignment="Left" Margin="82,55,0,0" VerticalAlignment="Top" Height="15" Width="85"/>
<ComboBox x:Name="ComboBox" HorizontalAlignment="Left" Margin="82,95,0,0" VerticalAlignment="Top" Width="369" Height="22">
<ComboBoxItem>THIS IS IT 1</ComboBoxItem>
<ComboBoxItem>THIS IS IT 2</ComboBoxItem>
<ComboBoxItem>THIS IS IT 3</ComboBoxItem>
</ComboBox>
<TextBox HorizontalAlignment="Center" Margin="0,140,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="408" Height="23"/>
<TextBox HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Center" Width="408" RenderTransformOrigin="0.333,0.782" Height="28"/>
</Grid>
</Grid>
</Window>
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 CopyandPaste
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
bool first = true;
StringBuilder value = new StringBuilder();
// some loop here
Clipboard.SetText(value.ToString());
}
}
}
I played with some foreach loops that were nested but of course got some results that were unwanted:
1
RadioButton
THIS IS IT 2
2
RadioButton
THIS IS IT 2
3
RadioButton
THIS IS IT 2
I understand what is going on here where the text box is causing the loop to continue. Trying to get some ideas or a point in the right direction to achieve an output like:
1
RadioButton
THIS IS IT 2
2
3
Any WPF UIElement has a Children property which will give you all its child controls. So you can use it to enumerate children and then loop through them. Something like;
foreach (var child in MasterGrid.Children)
{
// string builder code
}
You haven't quite clearly explained what your criteria to display a control is, but from the limited explanation you've given it looks like you want to grab the Text property if it's a TextBox, the SelectedItem if it is a ComboBox, and the name of the control if it is a RadioButton. These are quite different things when it comes to a control, so inside the loop you will have to check the type of each child control and get the right information.
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
StringBuilder value = new StringBuilder();
foreach (var child in MasterGrid.Children.OfType<Control>())
{
if (child.GetType() == typeof(TextBox))
{
value.Append(((TextBox)child).Text + Environment.NewLine);
}
else if (child.GetType() == typeof(RadioButton))
{
var rb = (RadioButton)child;
if (rb.IsChecked == true)
{
value.Append(rb.Name + Environment.NewLine);
}
}
else if (child.GetType() == typeof(ComboBox))
{
value.Append(((ComboBox)child).Text + Environment.NewLine);
}
}
MessageBox.Show(value.ToString());
}
Above is for the types of controls you've mentioned, you'll have to figure out what to do with other control types.
Next when it comes to order, there can be different meanings to the 'order' in controls in a WPF GUI.
Do you want the order in which they are listed in the XAML code?
Or do you want the order in which they are displayed when the program is run?
For example, in your code if you moved the last text box XAML code above the second-to-last, they will still appear in the original order when you run the program because you've hard-coded their locations (which in itself is a bad idea; you should use grids, stack panels etc to do your layout in WPF).
I think if you care about the order, best option is to modify your XAML and specify the Tag property of each control.
E.g.
<TextBox Grid.Column="1"
Width="408"
Height="23"
Margin="0,21,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="1"
TextWrapping="Wrap"/>
Then when you enumerate the children, do an order by tag before iterating through them.
This way you have firm control over whatever it is that you mean by order.
var children = MasterGrid.Children.OfType<Control>().OrderBy(x => x.Tag);
foreach (var child in children)
{
// Same as before
}

UWP: use 1 MediaSource for several Players

I have some uwp application, where several videos are played simultaneously. I thought it might be a good idea to use 1 media source to improve performance. But I'm not sure why this idea doesn't work.
MainPage.xaml:
<Page
x:Class="UWP_OneMediaSourceForSeveralPlayers.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWP_OneMediaSourceForSeveralPlayers"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Loaded="Page_Loaded">
<StackPanel Orientation="Vertical" Background="Yellow" Height="400" Width="200">
<MediaPlayerElement x:Name="Player1" Height="200" Width="200" />
<MediaPlayerElement x:Name="Player2" Height="200" Width="200" />
</StackPanel>
</Page>
MainPage.xaml.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace UWP_OneMediaSourceForSeveralPlayers
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var uri = new Uri(BaseUri, "/Assets/Videos/video.mp4");
var mediaSource = MediaSource.CreateFromUri(uri);
Player1.Source = mediaSource;
Player2.Source = mediaSource;
Player1.MediaPlayer.Play();
Player2.MediaPlayer.Play();
}
}
}
That's what I see:
So, looks like the first video is loaded. But not the second...
NOW question: why I can not use 1 media source for 2 players? How to make it work? Or do you have any other idea how to run the same file in several players?
P.S. creating 2 media sources from URI is not a good solution for me, because my app can have a lot (10+) videos running at the same time. If I create a media source for each player it will hurt performance.
So what you can actually do here is share a MediaPlayer between the two MediaPlayerElement instance.
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var uri = new Uri(BaseUri, "/Assets/Videos/video.mp4");
var mediaSource = MediaSource.CreateFromUri(uri);
var player = new MediaPlayer
{
Source = new MediaPlaybackItem(mediaSource)
};
Player1.SetMediaPlayer(player);
Player2.SetMediaPlayer(player);
player.Play();
}
If you don't require the transport controls from MediaPlayerElement, it's probably better to use MediaPlayerPresenter instead.

WPF menu - Dynamic show and hide content

I need to create interactive menu. When option was choosen, I want to show appropriate content.
For example when option "Schemat bazy Northwind" was clicked, to my grid should be added Image. When another option was choosen previous content is removed and etc.
The only thing that comes to my mind is create functions which at the beginning clear grid and later add content(Is it possible?).
Please there anybody could direct me to solve this problem.
<Window x:Class="Northwind.AdminPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Panel administratora" WindowState="Maximized">
<StackPanel Name="bindingData">
<StatusBar>
<TextBlock FontSize="15" Text="{Binding ServerName}" Margin="0 0 30 0"></TextBlock>
<TextBlock FontSize="15" Text="{Binding ConnectionStatus}" Margin="0 0 30 0"></TextBlock>
<Label FontSize="15" Name="lblClock"></Label>
</StatusBar>
<DockPanel Height="55">
<Menu DockPanel.Dock="Top">
<MenuItem Header="Baza" Margin="10" FontSize="15"></MenuItem>
<MenuItem Header="Pomoc" Margin="10" FontSize="15">
<MenuItem x:Name="itemSchema" Header="Schemat bazy Northwind" Click="itmSchema_Click_1"></MenuItem>
</MenuItem>
</Menu>
</DockPanel>
<Grid x:Name="mainContent">
<!--add content -->
</Grid>
</StackPanel>
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.Shapes;
using System.Windows.Threading;
namespace Northwind
{
public partial class AdminPanel : Window
{
public string ServerName { get; set; }
public string ConnectionStatus { get; set; }
public AdminPanel(string name,string status)
{
InitializeComponent();
this.ServerName = name;
this.ConnectionStatus = status;
DispatcherTimer dtClockTime = new DispatcherTimer();
dtClockTime.Interval = new TimeSpan(0, 0, 1);
dtClockTime.Tick += dtClockTime_Tick;
dtClockTime.Start();
bindingData.DataContext = this;
}
private void dtClockTime_Tick(object sender, EventArgs e)
{
lblClock.Content = DateTime.Now.ToLongTimeString();
}
private void itmSchema_Click_1(object sender, RoutedEventArgs e)
{
//code
}
}
}
You can put the menu or whichever item you wanted to a conatainer (Grid) and you can use the Visibility attribute as collapsed when you want to hide that control.
if you are not using MVVM pattern then add it into the corresponding Event.
Container_Name.Visibility = Visibility.Collapsed;
Or else you can use the Xaml Triggers for obtain the same.
For that refer StackOverflow_Answer
Create a resources Dictionary and add this code
<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Set names two different ways -->
<Button Name="okButton">OK</Button>
<Button x:Name="cancelButton">Cancel</Button>
<ListBox>
<!-- Set content three different ways -->
<ListBoxItem Content="Item 1" />
<ListBoxItem>Item 2</ListBoxItem>
<ListBoxItem>
<ListBoxItem.Content>Item 3</ListBoxItem.Content>
</ListBoxItem>
</ListBox> </StackPanel>
when option "Schemat bazy Northwind" was clicked
private void SchematbazyNorthwind_Click(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = null;
using (FileStream fs =
new FileStream("Dictionary1.xaml", FileMode.Open, FileAccess.Read))
{
stackPanel = (StackPanel)XamlReader.Load(fs);
}
MainGrid.Children.Add(stackPanel);
}
Load your Resources and attach to you grid

Data binding to hub section in C# XAML

I'm trying to design a very basic application for windows phone (C#/XAML). At first, I used the hub template, but I got lost so I decided to go step by step and started from a blank app and added a hub.
I managed to bind data between two distinct pages, with line codes such as TextBox.DataContext = DataContext ... but I'd like to bind data properly to hub sections, which is not as easy since hub elements lie in "DataTemplate" which cannot be accessed.
I spent the last two weeks reading documentation, tutorials, etc... Now I've read so many different sources that I am totally lost and do not know what I should do.
Here is my app : A "Players" class (player name and score); and a simple page with a hub control that has 2 sections.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace App1
{
class Players
{
private string playerName;
public string PlayerName
{
get { return playerName; }
set { playerName = value; }
}
private int playerScore;
public int PlayerScore
{
get { return playerScore; }
set { playerScore = value; }
}
}
}
The code behind is very basic, I just created a list of that I populated with only two players. All I want to do, for now, is to understand how the data binding can work.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace App1
{
public sealed partial class MainPage : Page
{
public MainPage()
{
List<Players> players = new List<Players>();
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
Players player1 = new Players(); Players player2 = new Players();
player1.PlayerName = "Vince"; player1.PlayerScore = 2; player2.PlayerName = "Mike"; player2.PlayerScore = 42;
players.Add(player1); players.Add(player2);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
All I'd like to do, for now, is to understand how the data binding works.
For example, I would like to have a TextBox in my hub that would display player1.PlayerName.
My XAML code, as of today looks as :
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<local:Players x:Key="PlayerDataSource"/>
</Page.Resources>
<Page.DataContext>
<Binding Source="{StaticResource PlayerDataSource}"/>
</Page.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Hub x:Name="Hub1" Grid.Row="1" DataContext="Players">
<HubSection x:Name="HubSec1">
<DataTemplate>
<StackPanel>
<TextBlock Text="Hello"></TextBlock>
<TextBox x:Name="tb1"></TextBox>
</StackPanel>
</DataTemplate>
</HubSection>
<HubSection x:Name="HubSec2">
<DataTemplate>
<StackPanel>
<TextBlock Text="Section2"></TextBlock>
<TextBlock Text="Trying to bind"/>
<TextBlock Text="{Binding PlayerName}"/>
</StackPanel>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
I know how to bind a full list to an element such as a listbox (with a ItemsSource={Binding} in XAML + ListBox.DataContext = players in code behind), but here I would like to display only one given element of my players...
I have tried to add a xmlns:data="clr-namespace" but this does not seem to be working (the IDE does not propose any auto-completion)
I am probably doing something wrong somewhere... but can't figure out where exactly. As mentionned above, I have tried so many different options that I am totally lost now...
OK, I finally found out what was wrong in my code.
First, in the xaml, for each list box, make sure to add the binding
<ListBox x:Name="lb" ItemsSource="{Binding}" Grid.Column="1">
Then, for example, to bind to a textbox, I simply added :
<TextBlock Text="{Binding PlayerName}" FontSize="32" Grid.Column="0"/>
And in the code behind, a simple :
MainHub.DataContext = players;
And that was it, everything binds perfectly now. Thanks for your help

Categories