I am creating the DataGridTemplateColumn dynamically.
var binding = new Binding
{
Path = new PropertyPath("MyProperty"),
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus
};
var converterParameter = new List<object> { header, rows, myGrid };
binding.Converter = new MyConverter();
binding.ConverterParameter = converterParameter;
var textBoxValue = new FrameworkElementFactory(typeof(TextBox));
totalUnitsValue.SetBinding(TextBox.TextProperty, binding);
totalUnitsValue.SetValue(TextBox.HorizontalContentAlignmentProperty, HorizontalAlignment.Right);
totalUnitsValue.SetValue(TextBox.WidthProperty, 40.0);
totalUnitsValue.SetValue(TextBox.MarginProperty, new Thickness(4, 0, 10, 0));
var factoryElement = new FrameworkElementFactory(typeof(StackPanel));
factoryElement.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
factoryElement.AppendChild(textBoxValue );
var column = new DataGridTemplateColumn
{
Header = header,
CellTemplate = new DataTemplate { VisualTree = factoryElement }
};
myGrid.Columns.Add(column);
This works fine for few columns. But if i create 10 or more columns (80 -90) textBoxes then the last created TextBoxes do not allow me to change the value or do not allow me to put focus on the TextBox. It becomes like TextBlock.
EDIT:
IF I REMOVE THE STACKPANEL, THEN THERE IS NO ISSUE WITH THE TEXTBOX BUT I NEED TO SHOW MORE THAN ONE ELEMENT, SO I NEED TO HAVE SOME SORT OF CONTAINER.ANY HELP ON THAT.
Please guide what could be tghe
Related
I am trying to read an "ini" file and to create multiple radiobuttons depending on the number of the lines of this file. The code used is the following:
private void CreateRadioButtons(string filePath)
{
StackPanel mainStackPanel = new StackPanel();
mainStackPanel.Orientation = Orientation.Vertical;
mainStackPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
mainStackPanel.VerticalAlignment = VerticalAlignment.Stretch;
var lines = File.ReadAllLines(filePath).Where(l => !l.StartsWith(";"));
WrapPanel wrapPanel = new WrapPanel();
wrapPanel.Margin = new Thickness(30);
ScrollViewer scrollViewer = new ScrollViewer();
Style style = new Style(typeof(RadioButton));
style.Setters.Add(new Setter(RadioButton.BackgroundProperty, Brushes.Yellow));
style.Setters.Add(new Setter(RadioButton.BorderThicknessProperty, new Thickness(2)));
ControlTemplate controlTemplate = new ControlTemplate(typeof(RadioButton));
FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
border.SetValue(Border.BorderThicknessProperty, new TemplateBindingExtension(BorderThicknessProperty));
border.SetValue(Border.BorderBrushProperty, new TemplateBindingExtension(BorderBrushProperty));
border.SetValue(Border.BackgroundProperty, Brushes.Transparent);
border.SetValue(Border.CornerRadiusProperty, new CornerRadius(20));
border.SetValue(BorderBrushProperty, new SolidColorBrush(Colors.Blue));
border.SetValue(Border.BackgroundProperty, Brushes.Transparent);
FrameworkElementFactory image = new FrameworkElementFactory(typeof(Image));
image.SetValue(Image.SourceProperty, new BitmapImage(new Uri("pack://application:,,,/Resources/image.jpg")));
FrameworkElementFactory textBlock = new FrameworkElementFactory(typeof(TextBlock));
textBlock.Name = "TextBlock";
textBlock.SetValue(TextBlock.TextProperty, "Text");
textBlock.SetValue(TextBlock.MarginProperty, new Thickness(5));
FrameworkElementFactory secondaryStack = new FrameworkElementFactory(typeof(StackPanel));
secondaryStack.SetValue(StackPanel.OrientationProperty, Orientation.Vertical);
secondaryStack.SetValue(StackPanel.MarginProperty, new Thickness(5, 10, 5, 0));
secondaryStack.AppendChild(image);
secondaryStack.AppendChild(textBlock);
border.AppendChild(secondaryStack);
controlTemplate.VisualTree = border;
style.Setters.Add(new Setter(Control.TemplateProperty, controlTemplate));
Trigger trigger = new Trigger() { Property = RadioButton.IsCheckedProperty, Value = false };
trigger.Setters.Add(new Setter(UIElement.OpacityProperty, 0.5));
style.Triggers.Add(trigger);
FrameworkElementFactory label = new FrameworkElementFactory(typeof(Label));
foreach (var line in lines)
{
RadioButton radioButton = new RadioButton();
radioButton.Style = style;
radioButton.Width = 135;
radioButton.Height = 125;
radioButton.Margin = new Thickness(15, 0, 0, 15);
radioButton.Content = border;
wrapPanel.Children.Add(radioButton);
}
This code is functioning at the moment. The problem comes when i try to implement textblocks with dynamic text: I just need the text inside the radiobutton to be equal to the string line. I have tried multiple ways but in the end I only encounter exceptions about windowspresentation (which I think mean that the elements are presented in the wrong way). How can I make textBlock dynamic?
I have an ObservableCollection with a list of users' data which is wrapped for multiselect page.
I added SearchBar to the multiselect page but I cannot make it work.
Code
public class WrappedItemSelectionTemplate : ViewCell
{
public WrappedItemSelectionTemplate() : base()
{
Label Title = new Label() { TextColor = Color.Black };
Title.SetBinding(Label.TextProperty, new Binding("Item.Title"));
Label Email = new Label() { FontSize = 14 };
Email.SetBinding(Label.TextProperty, new Binding("Item.Email"));
Switch mainSwitch = new Switch() { HorizontalOptions = LayoutOptions.End };
mainSwitch.SetBinding(Switch.IsToggledProperty, new Binding("IsSelected"));
StackLayout Stack = new StackLayout();
Stack.Children.Add(Title);
Stack.Children.Add(Email);
Grid grid = new Grid();
grid.Children.Add(Stack, 0,0);
grid.Children.Add(Email, 0, 1);
grid.Children.Add(mainSwitch, 1, 0);
View = grid;
}
}
public List<WrappedSelection<T>> WrappedItems = new List<WrappedSelection<T>>();
public SelectMultipleBasePage(List<T> items)
{
WrappedItems = items.Select(item => new WrappedSelection<T>() { Item = item, IsSelected = false }).ToList();
ListView mainList = new ListView()
{
ItemsSource = WrappedItems,
ItemTemplate = new DataTemplate(typeof(WrappedItemSelectionTemplate)),
};
mainList.ItemSelected += (sender, e) =>
{
if (e.SelectedItem == null) return;
var o = (WrappedSelection<T>)e.SelectedItem;
o.IsSelected = !o.IsSelected;
((ListView)sender).SelectedItem = null; //de-select
};
// SearchBar added
StackLayout Stack = new StackLayout();
SearchBar Search = new SearchBar();
Stack.Children.Add(Search);
Stack.Children.Add(mainList);
Search.TextChanged += (sender, e) =>
{
SearchBar_TextChanged();
};
Content = Stack;
void SearchBar_TextChanged()
{
//string keyword = Search.Text;
//mainList.ItemsSource =
}
}
When I used SearchBar in my cases before I was using new ObservableCollection for ItemsSource of my ListView, it was filtering it as I required.
But now am stuck and don't know how I can use the SearchBar for the field Title in that case with WrappedItems?
Although I prefer to see the code in Xaml and bound to VM with MVVM binding to make it easier to read . But I think I got what you need.
What you need to :
Search within WrappedItems and save the found result
Clear the ItemSource of the list view mainList.ItemSource.Clear();
Go through the foundItems and mainList.ItemSource.Add(foundItem);
If the Key is empty string "" then you go through original list and do the same work (i.e. clear the itemsource and add the whole data )
So I have this program where I mainly do all my bindings by using x:Bind but I have a control page where I need to generate a lot of Slider to be able to manipulate the data I stored in an ObservableCollection<T>
I really need to generate those sliders from my code because I need around 100 of them and it would really mess up my xmal file to create them by hand...
This is how I create the bindings in my code. They also work when I load them the first time. But they don't change the source data when I move the slider around.
private void CreateGrid()
{
for (var parameterNumberIndex = 1; parameterNumberIndex < 97; parameterNumberIndex++)
{
var paraName = new TextBlock()
{
Name = $"Parameter{parameterNumberIndex}",
FontSize = 25,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(0, 0, 0, 10)
};
var slider = new Slider()
{
Name = $"ValueSlider{parameterNumberIndex}",
Width = 200,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
var value = new TextBox()
{
Name = $"ValueBox{parameterNumberIndex}",
Margin = new Thickness(10, 5, 0, 0),
FontSize = 20,
VerticalAlignment = VerticalAlignment.Top
};
var row = new RowDefinition { Height = new GridLength(50, GridUnitType.Pixel) };
SettingsGrid.RowDefinitions.Add(row);
var nameBinding = new Binding
{
Source = ViewModel.BlockCollection.NamesBlock.Names[parameterNumberIndex].NameString,
Mode = BindingMode.OneWay
};
var valueBinding = new Binding()
{
Source = ViewModel.BlockCollection.ParameterBlock.Parameters[parameterNumberIndex].ParameterValue,
Mode = BindingMode.TwoWay
};
var minBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MinValue,
Mode = BindingMode.OneWay
};
var maxBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MaxValue,
Mode = BindingMode.OneWay
};
var textBinding = new Binding()
{
Path = new PropertyPath("Value"),
Source = slider,
Mode = BindingMode.TwoWay
};
BindingOperations.SetBinding(paraName, TextBlock.TextProperty, nameBinding);
BindingOperations.SetBinding(slider, Slider.MinimumProperty, minBinding);
BindingOperations.SetBinding(slider, Slider.MaximumProperty, maxBinding);
BindingOperations.SetBinding(slider, Slider.ValueProperty, valueBinding);
BindingOperations.SetBinding(value, TextBox.TextProperty, textBinding);
SettingsGrid.Children.Add(paraName);
SettingsGrid.Children.Add(slider);
SettingsGrid.Children.Add(value);
Grid.SetColumn(paraName, 0);
Grid.SetColumn(slider, 1);
Grid.SetColumn(value, 2);
Grid.SetRow(paraName, parameterNumberIndex - 1);
Grid.SetRow(slider, parameterNumberIndex - 1);
Grid.SetRow(value, parameterNumberIndex - 1);
}
}
The Source = ... are always ObservableCollection<T> depending on which type I need them in.
The slider source is a collection of uint.
The BindableBase is my implementation of INotifyPropertyChanged.
public class ParameterBlock : BindableBase
{
public ParameterBlock()
{
this.Parameters = new ObservableRangeCollection<ParameterBlockValue>();
}
public ObservableRangeCollection<ParameterBlockValue> Parameters
{
get => _parameters;
set
{
_parameters = value;
OnPropertyChanged();
}
}
private ObservableRangeCollection<ParameterBlockValue> _parameters;
}
public class ParameterBlockValue : BindableBase
{
private uint _parameterValue;
public uint ParameterValue
{
get => _parameterValue;
set
{
_parameterValue = value;
OnPropertyChanged();
}
}
public ParameterBlockValue(uint parameter)
{
this.ParameterValue = parameter;
}
public override string ToString()
{
return $"{this.ParameterValue} {Environment.NewLine}";
}
}
This is nearly the last step I need to fix before I'm more or less done with this project and I don't want to get stuck here :/
I don't know if the wpf tag is wrong. But everytime I look for xaml references I stumble over the wpf stuff and it's somewhat usable. So if it's wrong just tell me and I remove it.
To explain a bit more... In the finished product it will depend on what data I recieve to decide if there will be a slider or a textbox.
Just a small example picture from another question I had yesterday:
I see you are adding the controls in a Grid, generating the rows manually. While this could certainly work, it would be much better to use a list control and create the items within:
<ItemsControl ItemsSource="{x:Bind Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your Sliders, etc. -->
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl>
If the data might vary between multiple layouts, you may implement a DataTemplateSelector class, override the SelectTemplateCore(object item, DependencyObject container) (this method specifically, there is another one with the same name but different number of parameters which is not called) and decide on the right template for each item. You can create multiple DataTemplates as resources with x:Key and then reference them from your DataTemplateSelector. See this blog post for an example and documentation for more details.
I have defined the following Cell type in a Xamarin.Forms project:
public MyCell() // constructor
{
var messageLabel = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
FontAttributes = FontAttributes.Bold,
};
messageLabel.SetBinding(Label.TextProperty, new Binding("Message"));
var dateLabel = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label))
};
dateLabel.SetBinding(Label.TextProperty, new Binding("Date"));
var view = new StackLayout
{
Children = { messageLabel, dateLabel },
Orientation = StackOrientation.Vertical,
};
View = view;
}
This is called within a ListView, like so:
public MyPage()
{
var listView = new ListView()
{
ItemsSource = GetAllitems(),
ItemTemplate = new DataTemplate(typeof(MyCell)),
};
Content = listView
}
When this renders on the screen each item is really squashed up against its neighbours. I tried adding padding to the StackLayout in the MyCell class, but doing so results in text going off the screen. I'd like to have a gap between each item.
I'm think it may be worth converting the view to use Xaml to make this more clear, so if its easier to achieve as Xaml I'd accept that as an answer!
Set the HasUnevenRows property to true on the ListView. That way you have more control over the cell size.
Also, leave RowHeight to its default value (-1).
I am new to windows phone. I am trying to make pivot of questions . I want to add a text block and 2 radio buttons on each pivot item . I managed to add the textbook but didn't know how to add radio buttons.
var count = i + 1;
var textblok = new TextBlock { Text = o["questions"][i]["question"].ToString(), FontSize = 20,Width=450};
textblok.TextWrapping = TextWrapping.Wrap;
quizPivot.Items.Add(new PivotItem { Name="question"+count, Header = "Question " + count, Content = textblok,});
after adding container
for (var i = 0; i < Globals.quizcount; i++)
{
var count = i + 1;
var stackpanel = new StackPanel();
var textblok = new TextBlock { Text = o["questions"][i]["question"].ToString(), FontSize = 20,Width=450};
textblok.TextWrapping = TextWrapping.Wrap;
stackpanel.Children.Add(textblok);
var radio = new RadioButton { Name = "useransYes", Content = "Yes" };
stackpanel.Children.Add(radio);
var radio1 = new RadioButton { Name = "useransNo", Content = "No" };
stackpanel.Children.Add(radio1);
//, HorizontalAlignment = "Left", Margin = "66,317,0,0", VerticalAlignment = "Top
quizPivot.Items.Add(new PivotItem { Name = "question" + count, Header = "Question " + count, Content = stackpanel });
quesId.Text = o["questions"][i]["_id"].ToString();
}
2nd i want to know how to get all the pivot items i mean the contents in it.
Thanks
You need to use a container control to add multiple UI controls to single PivotItem. For example using StackPanel as container :
//create the container
var stackpanel = new StackPanel();
//create textblock
var textblok = new TextBlock { Text = o["questions"][i]["question"].ToString(), FontSize = 20,Width=450};
textblok.TextWrapping = TextWrapping.Wrap;
//add to container
stackpanel.Children.Add(textblok);
//create radiobutton
var radiobutton = new RadioButton{Content = "Radio Button content"}
//add to container
stackpanel.Children.Add(radiobutton);
//add the container as content of pivot item
quizPivot.Items.Add(new PivotItem { Name="question"+count, Header = "Question " + count, Content = stackpanel,});
Anyway, there is another way around to accomplish this with much cleaner approach. Avoid creating UI controls from code by using data-binding and templating pivot item.