Reputation: 1529
I am c# and silverlight beginner and i have a situation where i dynamically create combo box and add it in list.
if (p.Component.Type == "Combo")
{
var cb = new ComboBox();
foreach (var item in p.Component.Attributes.Items)
{
cb.Items.Add(item); //These item contains a l0,15,45,60 to select through combo box
}
result.Add(cb);
}
I have many other things like "TextBlock","TextBox" etc. things to add in this list. Suppose i also have to add this TextBlock in same list with one more if condition like this :
if (true)
{
var txtblk = new TextBlock();
txtblk.Text = "Max Amount";
result.Add(txtblk);
}
Now the outout obtained is like this :
I mean it is always at Top=Left=0. (I mean they overlaps)
Now question is how to give these GUI elements different position in the same list ? Please do not hesitate to ask me if you still don't understand the question.
Note: I am using silverlight5 My xaml code is (My container is canvas) :
<UserControl x:Class="RenderingTest.MainPage"
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:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:this="clr-namespace:RenderingTest.Converters"
xmlns:sdh="clr-namespace:RenderingTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<this:MyValueConverter x:Key="TabConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Green">
<sdh:MyItemsControl ItemsSource="{Binding Path=TabList, Mode=OneWay, Converter={StaticResource TabConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Gray"> </Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Background="red" Height="100" Canvas.Left="10" Canvas.Top="100" >
<ContentPresenter/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</sdh:MyItemsControl>
</Grid>
</UserControl>
EDIT: I have added the photo of GUI which is supposed to be achieved and also the xml i deserialized(which i am sure that it is properly deserialized i can see that on debugging) (here Parameter is parent class)
EDIT2 (after thbe new answer):
My parameter.cs class is:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Collections;
namespace RenderingTest
{
[XmlRoot(ElementName = "parameter")]
public class Parameter
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("label")]
public string Label { get; set; }
[XmlElement("unit")]
public string Unit { get; set; }
[XmlElement("component")]
public Component Component { get; set; }
}
}
ViewModel.cs is : (please note that in ReadParameterXML() i pass the xml string in its parameter from MainPage.cs class)
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Collections;
using System.Collections.ObjectModel;
namespace RenderingTest
{
public class viewModel : GenericViewModel
{
private ObservableCollection<Parameter> tabList;
public ObservableCollection<Parameter> TabList
{
get { return tabList; }
set
{
tabList = value;
OnPropertyChanged("TabList");
}
}
#region Constructor
public viewModel()
{
tabList = new ObservableCollection<Parameter>();
}
#endregion
public void ReadParameterXML(String xmlstring)
{
XmlSerializer deserializer = new XmlSerializer(typeof(Parameter));
XmlReader reader = XmlReader.Create(new StringReader(xmlstring));
Parameter parameter = (Parameter)deserializer.Deserialize(reader);
foreach (var item in parameter.Component.Attributes.Items)
{
Debug.WriteLine(item);
}
tabList.Add(parameter);
Debug.WriteLine(parameter.Component.Type);
Debug.WriteLine(parameter.Name);
Debug.WriteLine(parameter.Label);
Debug.WriteLine(parameter.Unit);
}
}
}
MyConverter.cs is
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using System.Collections.Generic;
namespace RenderingTest.Converters
{
public class MyValueConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ICollection<Parameter> list = value as ICollection<Parameter>;
List<UIElement> result = new List<UIElement>();
if (list != null)
{
foreach (Parameter p in list)
{
if (p.Component.Type == "Combo")
{
StackPanel st = new StackPanel()
{
Orientation = Orientation.Horizontal
};
var txtblk = new TextBlock();
var txtblk2 = new TextBox();
txtblk.Text = p.Label;
var cb = new ComboBox();
foreach (var item in p.Component.Attributes.Items)
{
cb.Items.Add(item); //These item contains a l0,15,45,60 to select through combo box
}
cb.SelectedIndex = cb.Items.Count - 1;
txtblk2.Text = cb.SelectedValue.ToString() +" millions";
st.Children.Add(txtblk);
st.Children.Add(cb);
st.Children.Add(txtblk2);
// Canvas.SetTop(cb, itemHeight * i++);
result.Add(st);
}
}
}
return(result);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
}
MainPage.Xaml is
<UserControl x:Class="RenderingTest.MainPage"
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:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:this="clr-namespace:RenderingTest.Converters"
xmlns:sdh="clr-namespace:RenderingTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<this:MyValueConverter x:Key="TabConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Green">
<sdh:MyItemsControl ItemsSource="{Binding Path=TabList, Mode=OneWay, Converter={StaticResource TabConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Gray"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Background="red" Height="100" Canvas.Left="50" Canvas.Top="100" >
<ContentPresenter/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</sdh:MyItemsControl>
</Grid>
</UserControl>
Upvotes: 1
Views: 585
Reputation: 6415
Ok, from your edit one possible approach is:
NameString
, List<T>
, UnitsString
or are there other forms? If there are a range of these types then consider how much similarity there actually is, and whether they should be represented as one class or a few derived classes.parameter
classes, and bind that collection to an items control in your ViewBut the gist of it is:
ItemsSource
of an ItemsCollection UI component. Define the item template for this UI component to further bind the properties within your class to a specific kind of UI component appropriate to the kind of property you're dealing with.Upvotes: 1
Reputation: 102753
Take a look at some of the built-in panel controls. Choosing one of these and using it correctly is a good starting point to creating a layout for your view. A good one to start with is the StackPanel -- that adds each child control underneath the previous one.
Right now you're using the Canvas panel, which could also work, but you are not using it correctly. A Canvas needs each child element to define its Canvas.Left
and Canvas.Top
attached properties.
You're also making your life more difficult by using code-behind to construct a UI, rather than using XAML. You might want research data binding (starter example here), which is the core of Silverlight, before you undertake to build an app.
Edit
Here are two minimal examples of how you would position your items.
Option 1
Use a panel that automatically places its children:
<ItemsPanelTemplate>
<StackPanel Background="Gray" />
</ItemsPanelTemplate>
Option 2
If you're sure you want to use a Canvas, then you'll need to set Canvas.Left
and/or Canvas.Top
on each of the children. Here's a basic example of how, using Canvas.SetTop
:
int i=0;
double itemHeight = 30;
if (p.Component.Type == "Combo")
{
var cb = new ComboBox();
foreach (var item in p.Component.Attributes.Items)
{
cb.Items.Add(item); //These item contains a l0,15,45,60 to select through combo box
}
Canvas.SetTop(cb, itemHeight * i++);
result.Add(cb);
}
var txtblk = new TextBlock();
txtblk.Text = "Max Amount";
Canvas.SetTop(txtblk, itemHeight * i++);
result.Add(txtblk);
Upvotes: 1