I want to add a number of TextBlocks inside a Button. How can I add a number of them, along with StackPanels or Canvases, in C#, as shown below in XAMAL
<Button>
<StackPanel>
<TextBlock Text="ABC"/>
<TextBlock Text="DEF"/>
</StackPanel>
</Button>
It's easy:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var tb1 = new TextBlock() { Text = "TextBlock 1" };
var tb2 = new TextBlock() { Text = "TextBlock 2" };
var stackPanel = new StackPanel();
stackPanel.Children.Add(tb1);
stackPanel.Children.Add(tb2);
var button = new Button() { Content = stackPanel };
this.Content = button;
}
}
Maybe you should think about an enclosing control of csharpfolk's answer. This would help to get a reuseable control.
The text strings are good to use as a dependency property. :)
Regards,
- Tobbo
Related
I am building an C# UWP application where onclick of a button in the view a command (using System.Windows.Input.IComand) raises in viewmodel(not code behind) which builds a form of input fields like Name:____ phone:____ etc and shows it on the UI/view.
I dont want to keep the <ContentDialog></ContentDialog> in the
view.
What have I done so far is
Button in my view:
<CommandBar>
<AppBarButton x:Name="buttonNew" Command="{Binding AddClick}" />
</CommandBar>
ViewModel object in the code behind is set as the DataContext of the
View
In the view model:
public ICommand AddClick=> new RelayCommand(Add);
private async void Add()
{
TextBox input = new TextBox()
{
PlaceholderText = "Name",
};
var contentDialog = new ContentDialog
{
Title = "Add a Person",
Content = input,
FullSizeDesired = true,
PrimaryButtonText = "Add",
CloseButtonText = "Cancel"
};
await contentDialog.ShowAsync();
}
As you can see I am able to show/trigger a Content Dialog box with one input field and 2 buttons.
My problem is:
How to add more input fields like we add in a
<StackPanel></StackPanel> in the code of view model and assign it
to the content of the Content Dialog?
How to size it accordingly that all the fields show up properly and does not show up haphazard since am not coding this in the Xaml?
From the general application construction practice, it is recommended to create a UI using XAML to create a custom ContentDialog.
You don’t have to write the XAML code of ContentDialog in the View, you can add new item in Visual Studio, select the Content Dialog template, and create a custom dialog derived from ContentDialog.
Then use code similar to the following:
MyCustomDialog.xaml
<ContentDialog
...
Title="Add a Person"
FullSizeDesired="True"
PrimaryButtonText="Add"
CloseButtonText="Cancel"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick">
<StackPanel>
<TextBox Header="Name" x:Name="NameBox" PlaceholderText="Name"
HorizontalAlignment="Stretch"/>
<TextBox Header="Phone" x:Name="PhoneBox" PlaceholderText="Phone"
Margin="0,15,0,0" HorizontalAlignment="Stretch"
InputScope="Number"/>
</StackPanel>
</ContentDialog>
ViewModel.cs
private async void Add()
{
var dialog = new MyCustomDialog();
await dialog.ShowAsync();
}
If you insist on using C# code to create ContentDialog, you need to convert the tags in XAML into corresponding classes, but this method is not easy to debug.
private async void Add()
{
var container = new StackPanel();
TextBox nameBox = new TextBox()
{
PlaceholderText = "Name",
Header = "Name",
HorizontalAlignment = HorizontalAlignment.Stretch
};
TextBox phoneBox = new TextBox()
{
PlaceholderText = "Phone",
Header = "Phone",
HorizontalAlignment = HorizontalAlignment.Stretch,
Margin = new Thickness(0, 15, 0, 0)
};
container.Children.Add(nameBox);
container.Children.Add(phoneBox);
var contentDialog = new ContentDialog
{
Title = "Add a Person",
Content = container,
FullSizeDesired = true,
PrimaryButtonText = "Add",
CloseButtonText = "Cancel"
};
await contentDialog.ShowAsync();
}
The tags in XAML are actually the corresponding classes in C#, from the code you provided, the ContentDialog is displayed in full screen. You mentioned that you want the fields to be displayed correctly, if you mean that the string entered in the TextBox is too long and the text is not displayed completely, you can set the TextBox.TextWrapping property to True.
There is an existing code I have got but this is a dll and works with a third party app. I want to run it standalone to see how it works.So I create a grid on the cs coding side and invoke the grid from xaml. I have tried it in several ways but I have just provided the example below. I could not run it at all. Any help is appreciated.
CLASS
public partial class MainWindow : Window
{
Grid customGrid = new Grid();
public MainWindow()
{
customGrid.Children.Add(xxx);
customGrid.Children.Add(yyy);
}
}
XAML
<Grid Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center"
VerticalAlignment="Top">
<UserControl Grid.Row="3" HorizontalAlignment="Center"
VerticalAlignment="Top">
<Binding>
<Binding.Path>customGrid</Binding.Path>
</Binding>
</UserControl>
</Grid>
PS:I need to keep UserControl and Binding tags as they are.
Hi I have come up with this and it works as an example for anyone who needs it..
CLASS:
Grid customGrid = new Grid();
public MainWindow(){
InitializeComponent();
var tb = new TextBlock();
tb.Text = "sdasdadsas1";
customGrid.Children.Add(tb);
tb = new TextBlock();
tb.Text = "sdassssdas2";
customGrid.Children.Add(tb);
tb = new TextBlock();
tb.Text = "sdasdas3";
customGrid.Children.Add(tb);
this.DataContext = this;
}
public Grid gridTest
{
get { return customGrid; }
set { customGrid = value; }
}
XAML:
<UserControl Grid.Row="3" >
<Binding>
<Binding.Path>gridTest</Binding.Path>
</Binding>
</UserControl>
How to: Fill a ListView by using C# instead of using XAML
I would like to fill a ListView by using C# (WPF), not by using XAML. The reason for this is, that we do not know the number of elements before runtime.
This is my working XAML code:
<ListView Name="listView_BusinessContacts" SelectionMode="Single">
<ListViewItem Selected="ListViewItem_Selected">
<DockPanel DockPanel.Dock="Top" Name="dockPanel_1">
<Image DockPanel.Dock="Left" Source="/X;component/Images/folder.png" Stretch="None" />
<Label Content="Test 123" DockPanel.Dock="Right" Name="label_1" />
</DockPanel>
</ListViewItem>
</ListView>
My idea is first to create the ListViewItem. After that, I could create the DockPanel. But now, I do not know, how to add two elements to a DockPanel (here: Image and Label). After that, I would add the DockPanel to the ListViewItem and than I would add that ListViewItem to the ListView.
I hope, that you understand what I want to do.
Solution by SynerCoder:
public void SetListViewItems()
{
foreach (var item in File.ReadAllLines(#"C:\Companies\Companies.txt", Encoding.UTF8))
{
Image image = new Image();
image.Source = new BitmapImage(new Uri(#"Images\folder.png", UriKind.Relative));
image.Stretch = Stretch.None;
Label label = new Label();
label.Content = "Test 123";
DockPanel.SetDock(image, Dock.Left);
DockPanel.SetDock(label, Dock.Right);
DockPanel dockPanel = new DockPanel();
dockPanel.Children.Add(image);
dockPanel.Children.Add(label);
ListViewItem listViewItem = new ListViewItem();
listViewItem.Content = dockPanel;
listView_BusinessContacts.Items.Add(listViewItem);
}
}
You can use the following code to create your listview, use the static SetDock method of the DockPanel to set the docking positions.
var listView = new ListView();
foreach (var item in something)
{
var image = new Image();
image.Source = ...;
image.Stretch = Stretch.None;
var label = new Label();
label.Content = "Test 123";
DockPanel.SetDock(image, Dock.Left);
DockPanel.SetDock(label, Dock.Right);
var dockPanel = new DockPanel();
dockPanel.Children.Add(image);
dockPanel.Children.Add(label);
var item = new ListViewItem();
item.Content = dockPanel;
listView.Items.Add(item);
}
i have this (a rough e.g):
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label .../>
<TextBox .../>
<Button Content="Add new input row" ... />
</StackPanel>
</StackPanel>
pretty self explanatory, i want to add a new Horizontal StackPanel with every click on the button..
is that possible?
thank you!
For this XAML above I will do like this:
In the click event handle of every button name "Add new input row", I mean you can use this event for all of buttons.
private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
StackPanel stkButtonParent = btn.Parent as StackPanel;
StackPanel stkCover = stkButtonParent.Parent as StackPanel;
StackPanel newRow = NewRow();
stkCover.Children.Add(newRow);
}
private StackPanel NewRow() {
StackPanel stk = new StackPanel();
stk.Orientation = Orientation.Horizontal;
Label lbl = new Label();
lbl.Foreground = Brushes.Red; // some attribute
TextBox txt = new TextBox();
txt.Background = Brushes.Transparent; // some attribute
Button btn = new Button();
btn.Content = "Add new row";
btn.Click += btn_Click;
stk.Children.Add(lbl);
stk.Children.Add(txt);
stk.Children.Add(btn);
return stk;
}
Yes it is possible try handling the event like this for example:
// Create your StackPanel.
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
// Add controls to new StackPanel
// Control con = new Control();
// sp.Children.Add(con);
// Add created control to a previously created (and named) container.
myStackPanel.Children.Add(sp);
If you would like your StackPanel to contain some controls you can also add them to it here.
There is a way to do this via XamlReader as well, but I have never tried it.
Here is a link to a short article:
arcanecode.com
How to add a StackPanel in a Button using c# code behind (i.e. convert the following XAML to C# )? There is no Button.Children.Add...
<Button>
<StackPanel Orientation="Horizontal" Margin="10">
<Image Source="foo.png"/>
</StackPanel>
</Button>
Image img = new Image();
img.Source = new BitmapImage(new Uri("foo.png"));
StackPanel stackPnl = new StackPanel();
stackPnl.Orientation = Orientation.Horizontal;
stackPnl.Margin = new Thickness(10);
stackPnl.Children.Add(img);
Button btn = new Button();
btn.Content = stackPnl;
Set Button.Content instead of using Button.Children.Add
As a longer explanation:
Button is a control which "only has 1 child" - its Content.
Only very few controls (generally "Panels") can contain a list of zero or more Children - e.g. StackPanel, Grid, WrapPanel, Canvas, etc.
As your code already shows, you can set the Content of a Button to be a Panel - this would ehn allow you to then add multiple child controls. However, really in your example, then there is no need to have the StackPanel as well as the Image. It seems like your StackPanel is only adding Padding - and you could add the Padding to the Image rather than to the StackPanel if you wanted to.
Use like this
<Window.Resources>
<ImageSource x:Key="LeftMenuBackgroundImage">index.jpg</ImageSource>
<ImageBrush x:Key="LeftMenuBackgroundImageBrush"
ImageSource="{DynamicResource LeftMenuBackgroundImage}"/>
</Window.Resources>
and in Codebehind
Button btn = new Button();
btn.HorizontalContentAlignment = HorizontalAlignment.Stretch;
btn.VerticalContentAlignment = VerticalAlignment.Stretch;
StackPanel stk = new StackPanel();
stk.Orientation = Orientation.Horizontal;
stk.Margin = new Thickness(10, 10, 10, 10);
stk.SetResourceReference(StackPanel.BackgroundProperty, "LeftMenuBackgroundImageBrush");
btn.Content = stk;
In Xaml :
<Button x:Name="Btn" Click="Btn_Click" Orientation="Horizontal" Margin="10">
<StackPanel>
<Image Source="foo.png" Height="16" Width="16"/>
</StackPanel>
</Button>
In C# :
Button btn = new Button();
StackPanel panel = new StackPanel();
Image img = new Image
{
Source = "../foo.png"
}
panel.Children.Add(img);
btn.Content = panel;
I advise you to put the image in xaml resources :
<Window.Resources>
<BitmapImage x:Key="Img" UriSource="/Img/foo.png"/>
</Window.Resources>
And call it like this :
Image img = new Image
{
Source = (BitmapImage)FindResource("Img")
};