C# WPF better way to iterate on children and change property - c#

I have to iterate through all children of a stackPanel.
Being new to WPF I do that
foreach (var item in spTab3.Children)
{
if (item.GetType() == typeof(ListBox))
((ListBox)item).Visibility = Visibility.Collapsed;
if (item.GetType() == typeof(Grid))
((Grid)item).Visibility = Visibility.Collapsed;
....
}
that is I have to cast all types of elements to get to set the visibility. I bet there is a smarter way to do all the togheter.
Thanks
---EDIT---
So in short I have a stackpanel spTab3 with children.
When I do what suggested by Bijington:
spTab3.Visibility = Visibility.Collapsed;<----------set all children to collapsed
spTab3.Children[iVisibleTab-1].Visibility = Visibility.Visible;<----set only one to visible
the second line has no effect.
While when I do as stated by Spawn that works:
foreach (var item in spTab3.Children)
((UIElement)item).Visibility = Visibility.Collapsed;
spTab3.Children[iVisibleTab-1].Visibility = Visibility.Visible;
can anyone explain me why?!?

Every child in Panel is UIElement. So its type derived from DependencyObject which has SetValue method. Use it.
foreach (UIElement item in spTab3.Children)
{
item.SetValue(UIElement.VisibilityProperty, Visibility.Collapsed (or Visible));
}
Keep in mind that it's not a WPF style solution. You better need to declare dependency property and to bind item's visibility to this property.
In case that panel and code are inside a Window
public static readonly DependencyProperty IsItemVisibleProperty = DependencyProperty.Register("IsItemVisible", typeof(Visibility), typeof(MainWindow), new FrameworkPropertyMetadata(Visibility.Visible));
public Visibility IsItemVisible
{
get
{
return (Visibility)GetValue(IsItemVisibleProperty);
}
set
{
SetValue(IsItemVisibleProperty, value);
}
}
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Visibility="{Binding IsItemVisible,RelativeSource={RelativeSource AncestorType=Window}}">Collapsed 1</Button>
<Button Visibility="{Binding IsItemVisible,RelativeSource={RelativeSource AncestorType=Window}}">Collapsed 2</Button>
<Button>Visible</Button>
</StackPanel>
</Window>

A more efficient way of showing/hiding the Children within the StackPanel would be to simply set the Visibility property on the StackPanel itself.

Related

C# Wpf drawing with Combobox

I need help with drawing in my combobox. I want to make a combobox of colors for picking. I found some stuff on the internet but none of them is working. So far I have this :
private void MyComb_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
System.Drawing.Rectangle rect = e.Bounds;
ColorConverter converter = new ColorConverter();
if (e.Index >= 0)
{
string n = ((ComboBox)sender).Items[e.Index].ToString();
System.Drawing.Color c = (System.Drawing.Color)converter.ConvertFromString(n);
SolidBrush b = new SolidBrush(c);
g.FillRectangle(b, rect.X + 110, rect.Y + 5,
rect.Width - 10, rect.Height - 10);
}
}
This is my drawItem method
<Grid>
<ComboBox x:Name="MyComb" HorizontalAlignment="Left" Margin="66,81,0,0" VerticalAlignment="Top" Width="120" />
</Grid>
This is definition of combobox
Type colorType = typeof(System.Drawing.Color);
PropertyInfo[] propInfoList = colorType.GetProperties(BindingFlags.Static |
BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (PropertyInfo c in propInfoList)
{
MyComb.Items.Add(c.Name);
}
And here I am filling combobox with colors names and then I want to fill to combox with real colors according to the colors names.. But my draw item method is never called. I tried to create some DrawItem handler but, my combobox have no such thing... Then I read something about setting a DrawMode property of combobox, but my combobox doesn't that kind of property at all...
I am using net framework v.4.6.1
Can please anyone tell me, what am I missing ?
Thank you very much
The biggest problem you're having is that you're trying to use code examples that were written for the Winforms API, even though you are using the WPF API. For future reference, you really need to be more careful about identifying the context of tutorials and other resources you find online, to make sure they actually apply to your scenario.
As it happens, we have a number of related questions on Stack Overflow already:
WPF ComboBox as System.Windows.Media.Colors>
WPF - Bind ComboBox Item Foreground to Its Value
Very simple color picker made of combobox
These are all potentially useful to you, but are all based on the answer to this question:
How can I list colors in WPF with XAML?
Which was originally about just displaying the names of colors, and so took a short-cut, using the <ObjectDataProvider/> element in XAML. This led to the need to use a converter in the other questions, to convert either from a string value or a PropertyInfo instance to the appropriate color or brush.
In fact, if your code is already written to use some type of MVVM approach, and especially since you've already written code-behind to retrieve the color values from the Colors type, or at least tried to (one of the problems in your code is that you are using the Winforms Color type instead of the WPF Colors type…again, in Winforms that works fine, but the WPF API follows the Code Analysis/FxCop rules more closely, and the named colors are in the Colors type), it makes sense to just stick with that and provide a direct view model data structure to which you can bind.
In this approach, rather than providing a procedural implementation of the item drawing, you provide in XAML a declarative implementation describing what each item should look like.
Here is an example…
First, some simple view model data structures:
// Very simple container class
class ColorViewModel
{
public Brush Brush { get; }
public string Name { get; }
public ColorViewModel(Brush brush, string name)
{
Brush = brush;
Name = name;
}
}
// Main view model, acts as the data context for the window
class MainViewModel : INotifyPropertyChanged
{
public IReadOnlyList<ColorViewModel> Colors { get; }
private Brush _selectedColor;
public Brush SelectedColor
{
get { return _selectedColor; }
set { _UpdateField(ref _selectedColor, value); }
}
public MainViewModel()
{
Colors = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => new ColorViewModel(new SolidColorBrush((Color)p.GetValue(null)), p.Name))
.ToList().AsReadOnly();
}
public event PropertyChangedEventHandler PropertyChanged;
private void _UpdateField<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
With those in hand, the XAML is straight-forward:
<Window x:Class="TestSO47850587ColorComboBox.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:l="clr-namespace:TestSO47850587ColorComboBox"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:MainViewModel/>
</Window.DataContext>
<StackPanel>
<ComboBox Width="100" ItemsSource="{Binding Colors}"
HorizontalAlignment="Left" Grid.IsSharedSizeScope="True"
SelectedValuePath="Brush" SelectedValue="{Binding SelectedColor}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type l:ColorViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="ComboBoxItem"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Background="{Binding Brush}" HorizontalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Rectangle HorizontalAlignment="Stretch" Height="24" Fill="{Binding SelectedColor}"/>
</StackPanel>
</Window>
The above displays the color names, using the actual color as the background. If all you really want is a rectangle, then you can replace the <TextBlock/> element with a <Rectangle/> element, binding to its Fill property. Naturally, you can achieve other visual effects, such as a rectangle with a margin. It's just a matter of configuring your data template according to your need.
The main point here is that you should embrace the data binding approach that defines good WPF programming, and that you should definitely not mistake Winforms code examples for WPF. :)

XamlWriter.Save() is not serializing DependencyProperties

Consider the following XAML from my UserControl:
<TextBlock Text="HelloWorld" Loaded="TextBlock_OnLoaded" />
And the associated event handler:
private void TextBlock_OnLoaded(object sender, RoutedEventArgs e)
{
var xaml = XamlWriter.Save(sender);
Console.WriteLine(xaml);
}
When the TextBlock is loaded, the following output is written to the Console:
<TextBlock Text="HelloWorld" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
Now consider this alternative XAML:
<ListBox ItemsSource="{Binding SomeCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="HelloWorld" Loaded="TextBlock_OnLoaded" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now when the TextBlock is loaded, the following output is written to the Console:
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
......
Notice that the TextProperty is no longer being serialized.
If the following TextProperty assignment is added before the call to XamlWriter.Save():
private void TextBlock_OnLoaded(object sender, RoutedEventArgs e)
{
var textBlock = sender as TextBlock;
if (textBlock != null)
{
textBlock.Text = textBlock.Text;
}
var xaml = XamlWriter.Save(sender);
Console.WriteLine(xaml);
}
Then when the TextBlock is loaded, the following output is written to the Console:
<TextBlock Text="HelloWorld" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
<TextBlock Text="HelloWorld" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
<TextBlock Text="HelloWorld" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
......
Notice that the TextProperty is again being serialized.
This blog post explains that "... if the property is backed by a DependencyProperty ... the property is only written if it is actually set."
It appears that the TextProperty is indeed being set in the first usage example, but not in the second usage example with the ListBox and DataTemplate.
Can anyone explain why this is the case, and how to overcome this obstacle?
My best guess is that the XAML parser is somehow setting the TextBlock state internally instead of calling SetValue on the dependency property, but I'm not sure why it would do this only for elements inside a DataTemplate.
XamlWriter.Save appears to only serialize locally-set values. In XAML, values can come from multiple levels of sources.
When you set TextBlock.Text directly, you are looking at a "local value" set (precedence 3). However, when you set it inside a data template, you are setting template properties (precedence 4). By writing
textBlock.Text = textBlock.Text;
you are actually transforming that into a local property set (precedence 3)!
If you look at the some of the source code involved in XamlWriter.Save, you can see (line 819) that it explicitly reads the local value of the property.
Unfortunately, I'm not sure what a good work-around is for this. XamlWriter has known limitations. You an try inheriting from XamlDesignerSerializationManager and calling the XamlWriter.Save(Object, XamlDesignerSerializationManager) overload, but it doesn't look very promising. More likely, you will have to either do what you do above, or write your own serialization routine (at least Microsoft has made their source readily available as a guide).
In light of NextInLine's answer, I've come up with the following work around:
public static IEnumerable<DependencyProperty> GetDependencyProperties(this DependencyObject obj)
{
var propertyDescriptors = TypeDescriptor.GetProperties(obj, new Attribute[]
{
new PropertyFilterAttribute(PropertyFilterOptions.All)
});
return (from PropertyDescriptor pd in propertyDescriptors
let dpd = DependencyPropertyDescriptor.FromProperty(pd)
where dpd != null
select dpd.DependencyProperty).ToList();
}
public static IEnumerable<DependencyProperty> GetUpdatedDependencyProperties(this DependencyObject obj)
{
return (from property in obj.GetDependencyProperties().Where(x => !x.ReadOnly)
let metaData = property.GetMetadata(obj.GetType())
let defaultValue = metaData.DefaultValue
let currentValue = obj.GetValue(property)
where currentValue != defaultValue
select property).ToList();
}
Which can be used like this:
foreach (var updatedProperty in dependencyObject.GetUpdatedDependencyProperties())
{
dependencyObject.SetValue(updatedProperty, dependencyObject.GetValue(updatedProperty));
}
This will force XamlWriter.Save(dependencyObject) to serialize all of the dependencyObject properties that were updated in XAML.

To remove focus rectangle in WPFwithin a UserControl

I have a situation where I need to tab using TabKey from one control to another. The condition is that the focus should never go to control that does not have user inputs so only Text, ComboBox, List DatePicker but somehow the focus after 3 controls get the Focus to go to a dashed line Rectangle (Could be of a Grid, StackPanel, I have not been able to findout) around the control groups before it gets into the control. I have searched very thoroughly in Google and stack over flow for a solution but none seem to work.
Various solutions I tried:
1) Here I set FocusVisualStyle property to null right at start up for Grid and StackPanels. Created a new class:
<StackPanel views:FocusVisualTreeChanger.IsChanged="True" Name="parentStackPanel" Orientation="Vertical" Style="{DynamicResource key1}" FocusVisualStyle="{x:Null}">
public class FocusVisualTreeChanger
{
public static bool GetIsChanged(DependencyObject obj)
{
return (bool)obj.GetValue(IsChangedProperty);
}
public static void SetIsChanged(DependencyObject obj, bool value)
{
obj.SetValue(IsChangedProperty, value);
}
public static readonly DependencyProperty IsChangedProperty =
DependencyProperty.RegisterAttached("IsChanged", typeof(bool), typeof(FocusVisualTreeChanger), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, IsChangedCallback));
private static void IsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (true.Equals(e.NewValue))
{
FrameworkContentElement contentElement = d as FrameworkContentElement;
if (contentElement != null)
{
contentElement.FocusVisualStyle = null;
return;
}
FrameworkElement element = d as FrameworkElement;
if (element != null)
{
element.FocusVisualStyle = null;
}
}
}
}
Did not work.
I tried setting FocusVisualStyle property to null for only Grid and StackPanel seems to go through the codebehind if I put a break point but the focus rectangle does not go away:
<Grid Name="AppointmentGrid" Style="{DynamicResource key2}" FocusVisualStyle="{x:Null}">
Style style = new Style { TargetType = typeof(Grid) };
style.Setters.Add(new Setter(Grid.FocusVisualStyleProperty, null));
style.Setters.Add(new Setter(Grid.FocusableProperty, false));
Application.Current.Resources["key2"] = style;
Application.Current.Resources["key3"] = style;
Application.Current.Resources["key4"] = style;
Style style1 = new Style { TargetType = typeof(StackPanel) };
style1.Setters.Add(new Setter(StackPanel.FocusVisualStyleProperty, null));
style1.Setters.Add(new Setter(StackPanel.FocusableProperty, false));
Application.Current.Resources["key1"] = style1;
Can anyone please help me out with a solution that I have not already tried. None in stackoverflow solutions seem to work. I also set Focusable=false just incase but that doesn't seem to help either.
I also read:
Remove focus rectangle on a UserControl
WPF Control remove focus and hover effect (FocusVisualStyle?!)
WPF: Remove dotted border around focused item in styled listbox
This is what I think I am stuck at. A comment I found in one of the search sites.
That's a great way to change the default value of a DP, but it will not help in situations where a control's style explicitly changes the property value. Unfortunately, FocusVisualStyle is one such property. More specifically, styles for controls like Button, ComboBox, ListBox, etc. tend to explicitly contain a Setter for the FocusVisualStyle property. This setter will override the default value that you establish by overriding the metadata.
Can someone suggest a solution that will work in my case. I have a User control
<UserControl
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:csla="http://schemas.lhotka.net/4.2.0/xaml"
xmlns:input="clr-
FocusVisualStyle="{x:Null}"
Focusable="False"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
mc:Ignorable="d" d:DesignWidth="948"
IsTabStop="False"
TabIndex="-1">
<StackPanel views:FocusVisualTreeChanger.IsChanged="True" Name="parentStackPanel" Orientation="Vertical" Style="{DynamicResource key1}" FocusVisualStyle="{x:Null}"><Grid Name="AppointmentGrid" Style="{DynamicResource key2}" FocusVisualStyle="{x:Null}">
Thanks
Dhiren

Storyboards with bound properties (custom control: animate colour change)

To put it simply, I have this within a ControlTemplate.Triggers condition EnterAction:
<ColorAnimation To="#fe7" Storyboard.TargetProperty="Background.Color" Duration="00:00:00.1" Storyboard.TargetName="brd"/>
But I want the 'to' colour (#fe7) to be customisable. This is a control derived from ListBox. I can create a DependencyProperty, but of course, I cannot bind the To property of the ColorAnimation to it because the Storyboard has to be frozen and you can't freeze something with bindings (as I understand it).
I tried using a {StaticResource} within the To, then populating the resource in the code-behind when the DependencyProperty was changed, by setting this.Resources["ItemColour"] = newValue; for instance. That didn't work perhaps obviously, it's a static resource after all: no new property values were picked up. DynamicResource gave the same problem relating to inability to freeze.
The property is only set once when the control is created, I don't have to worry about it changing mid-animation.
Is there a nice way of doing this? Do I have to resort to looking for property changes myself, dynamically invoking and managing storyboards at that point? Or overlaying two versions of the control, start and end colour, and animating Opacity instead? Both seem ludicrous..
Kieren,
Will this serve your purpose?
I have extended the Grid class called CustomGrid and created a TestProperty whose value when changed will change the background color of Grid:
public class CustomGrid : Grid
{
public bool Test
{
get
{
return (bool)GetValue(TestProperty);
}
set
{
SetValue(TestProperty, value);
}
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(bool), typeof(CustomGrid),
new PropertyMetadata(new PropertyChangedCallback
((obj, propChanged) =>
{
CustomGrid control = obj as CustomGrid;
if (control != null)
{
Storyboard sb = new Storyboard() { Duration = new Duration(TimeSpan.FromMilliseconds(500)) };
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
ColorAnimation colAnim = new ColorAnimation();
colAnim.To = col;
colAnim.Duration = new Duration(TimeSpan.FromMilliseconds(500));
sb.Children.Add(colAnim);
Storyboard.SetTarget(colAnim, control);
Storyboard.SetTargetProperty(colAnim, new PropertyPath("(Panel.Background).(SolidColorBrush.Color)"));
sb.Begin();
}
}
)));
}
This is the button click event that changes the color:
private void btnClick_Click(object sender, RoutedEventArgs e)
{
gridCustom.Test = (gridCustom.Test == true) ? false : true;
}
I am changing the background color of Grid because I don't have your Listbox.
Finally this is the xaml:
<Grid x:Name="grid" Background="White">
<local:CustomGrid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" >
</local:CustomGrid>
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
Will this serve your purpose? Let me know or I misunderstood the question?
EDIT:
See this code:
ColorAnimation's To property cannot be bound as you probably guessed. But that doesn't mean you can't change it's value. You can always get a reference to the ColorAnimation and change it's To value and it will all work out well. So from WPF world of binding we need to change a bit and bind the data how we used to do it in Winforms :). As an example see this:
This is the xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ControlTemplateTriggers.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="Storyboard">
<ColorAnimation From="Black" To="Red" Duration="00:00:00.500" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="gridCustom" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid" Background="White">
<Grid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" />
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
</Window>
This is the code behind:
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System;
namespace Sample {
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void btnClick_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = this.Resources["Storyboard"] as Storyboard;
if (sb != null)
{
ColorAnimation frame = sb.Children[0] as ColorAnimation;
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
frame.To = col;
sb.Begin();
}
}
}
}
As you can see I am getting a reference to the storyboard and changing it's To property. Your approach to StaticResource obviously wouldn't work. Now what you can do is, in your DependencyProperty callback somehow get a reference to the Timeline that you want to animate and using VisualTreeHelper or something and then set it's To property.
This is your best bet.
Let me know if this solved your issue :)
can u put multiple DataTriggers with each having respective color for the "To" property...
Surely not..
What i understood is that u want color A on the Condition A and Color B on some other condition B....so if there's a property with multiple options u can put datatriggers for those condition only...like if Job done = Red, Half done = Green like wise..
If i misunderstood the problem please correct me..
I think i got ur question ...UR control is user configurable so what ever user select , control's background needs to be set to that color with animation right?
It turns out this is simply not possible.

Dynamic Grid In Silverlight 2 using C#

I need to insert UIElements into a Grid that does not get generated until runtime. More specifically, I need to add UIElements to the RowDefinitions I create after I determine how many elements need to be displayed. Is there a way to contorl the Grid.Row and Grid.Column and Grid.RowSpan like in XAML for objects in C#? If I am going about this wrong, please let me know. I can not use a StackPanel (I am creating an dynamic accordian panel and it messes with the animation).
Right now what happens is that I generate the number of RowDefinitions at runtime and add UIElements as the children. This isn't working, all the UIElements end up in the first row layered on top of each other.
Here is an example of what I am trying:
public partial class Page : UserControl
{
string[] _names = new string[] { "one", "two", "three" };
public Page()
{
InitializeComponent();
BuildGrid();
}
public void BuildGrid()
{
LayoutRoot.ShowGridLines = true;
foreach (string s in _names)
{
LayoutRoot.RowDefinitions.Add(new RowDefinition());
LayoutRoot.Children.Add(new Button());
}
}
}
Thanks!
Apart from the Grid not really being the right tool for the job (a ListView would be) you need to tell the Button which row it belongs to.
public void BuildGrid()
{
LayoutRoot.ShowGridLines = true;
int rowIndex = 0;
foreach (string s in _names)
{
LayoutRoot.RowDefinitions.Add(new RowDefinition());
var btn = new Button()
LayoutRoot.Children.Add(btn);
Grid.SetRow(btn, rowIndex);
rowIndex += 1;
}
}
The best way to do what you're looking for is to follow the pattern below:
Page.xaml:
<UserControl x:Class="SilverlightApplication1.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<data:DataGrid x:Name="DataGridTest" />
</Grid>
</UserControl>
Page.xaml.cs:
public partial class Page : UserControl
{
string[] _names = new string[] { "one", "two", "three" };
public Page()
{
InitializeComponent();
BuildGrid();
}
public void BuildGrid()
{
DataGridTest.ItemsSource = _names;
}
}
This builds the rows dynamically from the contents of your string array. In future an even better way would be to use an ObservableCollection where T implements INotifyPropertyChanged. This will notify the DataGrid to update it's rows if you remove or add an item from the collection and also when properties of T change.
To further customize the UIElements used to display things you can use a DataGridTemplateColumn:
<data:DataGridTemplateColumn Header="Symbol">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PutNameOfPropertyHere}" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
I have never used this stuff, but shouldn't you be adding the Button to the RowDefinitions, instead of the Children? (just a logical observation)

Categories

Resources