(ViewModel)DataContext returning null - c#

I've got the following event:
private void PlaceToken(object sender, RoutedEventArgs e)
{
ConnectFourViewModel currentViewModel = (ConnectFourViewModel)DataContext;
Button button = (Button)sender;
int currentColumn = Convert.ToInt32(button.Content);
int currentPlayer = currentViewModel.Board.CurrentPlayer;
currentViewModel.Board.PlaceToken(currentColumn, currentPlayer);
}
After the following set up:
public MainWindow()
{
var window = new Window();
var grid = new Grid {};
ConnectFourViewModel ViewModel = new ConnectFourViewModel();
//Set up rows and cols
for(int i = 1; i<=7; i++)
{
var col = new ColumnDefinition();
grid.ColumnDefinitions.Add(col);
}
for (int i = 1; i <= 7; i++)
{
var row = new RowDefinition();
grid.RowDefinitions.Add(row);
}
//Set up tiles
foreach (var item in ViewModel.Board.AllTiles)
{
int index = ViewModel.Board.AllTiles.IndexOf(item);
string name =
"Col" +
Convert.ToString(item.Column) +
"_Row" +
Convert.ToString(item.Row);
Label currentTile = new Label{ Name = name};
Grid.SetRow(currentTile, item.Row - 1);
Grid.SetColumn(currentTile, item.Column -1);
//Bind
var binding = new Binding();
binding.Source = ViewModel.Board.AllTiles[index];
binding.Path = new PropertyPath("Contents");
currentTile.SetBinding(ContentProperty, binding);
//Add
grid.Children.Add(currentTile);
}
//Set up Buttons
for (int i = 1; i <= 7; i++)
{
Button currentButton = new Button { };
//binding
var binding = new Binding();
binding.Source = ViewModel.CurrentColumn;
currentButton.SetBinding(ContentProperty, binding);
//Set Column names, this has to be after the binding has been set.
currentButton.Content = i;
//events
currentButton.Click += new RoutedEventHandler(PlaceToken);
//add
Grid.SetColumn(currentButton, i - 1);
Grid.SetRow(currentButton, 7);
grid.Children.Add(currentButton);
}
window.Content = grid;
window.DataContext = ViewModel;
window.Show();
InitializeComponent();
}
I'm expecting the line ConnectFourViewModel currentViewModel = (ConnectFourViewModel)DataContext; to set currentViewModel to reflect the information my UI is running off. Unfortunately it's returning null and I'm not sure why.
This is clearly highlighting a gap in my understanding of the topic, but unsure on how to tackle it I could use a hand.
Any idea where I've gone wrong?

You haven't assigned the DataContext to ViewModel anywhere. Assuming you want the ViewModel to be the ViewModel of MainWindow, I suggest you assigne it before Initialize Component as shown below. Since it's never assigned you are getting null.
public MainWindow()
{
ConnectFourViewModel ViewModel = new ConnectFourViewModel();
. . .
. . .
DataContext = ViewModel ;
InitializeComponent();
}

Related

How to programmatically set tab order

I am building a window from code.
I add a header TextBlock and then some various elements for a listBox in which each element is made out of
Grid ---> children[0] a TextBlock to explain what is the element
---> children1 a TextBox or combobox to input data.
At the end a button.
After having generated put the focus on the first element (generally the first TextBox) so that the user can immediately input data. Up to that everything works.
--ADD--
I forgot to mention that every element = Grid = Textblock + TextBox or combobox, is an element of the parent listBox. So I would like to move from every textbox or combobox independently from the listbox element they are in.
After that I want the user to be able to move to next element (textbox or combobox) through TAB. So when generating the previous windows I use a counter and set
tb.TabIndex = tabIndex++;
or
ComboBox.TabIndex = tabIndex++;
Now the problem is that after having input data in the first TextBox when I press TAB the caret gets lost and so the focus...
---ADD2---
Here is the code:
private void PreparareTraceFieldGrid(ListBox lbTracefields, ObservableCollection<Tuple<string, object, object>> obc, bool IsReadOnly)
{
bool IsFocusSet = false;
/*---TITOLO---*/
OutlinedTextBlock otbTitle = CreateOtbForTraceFieldInputWindow(Languages.Word(eWords.InsertTracefields));
lbTracefields.Items.Add(otbTitle);
/*----CICLO----*/
int tabIndex = 0;
foreach (var item in obc)
{
Grid gridInternal = new Grid();
gridInternal.Background = Brushes.Transparent;
ColumnDefinition cd1 = new ColumnDefinition();
cd1.Width = new GridLength(300, GridUnitType.Pixel);
ColumnDefinition cd2 = new ColumnDefinition();
cd2.Width = new GridLength(1.0, GridUnitType.Star);
gridInternal.ColumnDefinitions.Add(cd1);
gridInternal.ColumnDefinitions.Add(cd2);
OutlinedTextBlock otb = CreateOtbForTraceFieldInputWindow(item.Item1);
otb.FontSize = easyRunData.OptionsGraphical.FontSize;
otb.Stroke = new SolidColorBrush(easyRunData.OptionsGraphical.StrokeColour);
otb.StrokeThickness = easyRunData.OptionsGraphical.StrokeSize;
Grid.SetColumn(otb, 0);
gridInternal.Children.Add(otb);
string strDataType = item.Item2.ToString();
eTraceFieldDataTypes eDataType = (eTraceFieldDataTypes)Enum.Parse(typeof(eTraceFieldDataTypes), strDataType);
switch (eDataType)
{
case eTraceFieldDataTypes.STRING:
case eTraceFieldDataTypes.FLOAT:
case eTraceFieldDataTypes.INTEGER:
case eTraceFieldDataTypes.STRING_READONLY:
TextBox tb = new TextBox();
tb.CaretBrush = Brushes.White;
tb.FontSize = easyRunData.OptionsGraphical.FontSize;
tb.MinWidth = 200;
tb.Height = easyRunData.OptionsGraphical.FontSize + 15;
tb.VerticalAlignment = VerticalAlignment.Center;
tb.Background = Brushes.Transparent;
tb.Margin = new Thickness(10);
tb.TabIndex = tabIndex++;
tb.KeyDown += (senderEvent, args) => { AnalyzeTraceFields_IF_EMPTY(easyRunData.Tracefields.TraceFieldsUser, (Grid)lbTracefields.Parent); };
if (eDataType == eTraceFieldDataTypes.STRING_READONLY && !IsReadOnly)
tb.BorderBrush = Brushes.Yellow;
else
tb.BorderBrush = Brushes.Gainsboro;
Grid.SetColumn(tb, 1);
gridInternal.Children.Add(tb);
lbTracefields.Items.Add(gridInternal);
if (!IsFocusSet)
{
tb.Focus();
IsFocusSet = true;
}
break;
case eTraceFieldDataTypes.BOOL:
case eTraceFieldDataTypes.BOOL_READONLY:
Border brd = new Border();
brd.Margin = new Thickness(10);
brd.MinWidth = 200;
brd.Height = easyRunData.OptionsGraphical.FontSize + 15;
if (eDataType == eTraceFieldDataTypes.BOOL_READONLY && !IsReadOnly)
brd.BorderBrush = Brushes.Yellow;
else
brd.BorderBrush = Brushes.Gainsboro;
brd.BorderThickness = new Thickness(3);
ComboBox cmb = new ComboBox();
cmb.VerticalAlignment = VerticalAlignment.Center;
cmb.Background = Brushes.Transparent;
cmb.Items.Add(Languages.Word(eWords.True));
cmb.Items.Add(Languages.Word(eWords.False));
cmb.BorderBrush = Brushes.Gainsboro;
cmb.BorderThickness = new Thickness(3);
cmb.Margin = new Thickness(0);
cmb.TabIndex = tabIndex++;
cmb.DropDownClosed += (senderEvent, args) => { AnalyzeTraceFields_IF_EMPTY(easyRunData.Tracefields.TraceFieldsUser, (Grid)lbTracefields.Parent); };
Grid.SetColumn(brd, 1);
brd.Child = cmb;
gridInternal.Children.Add(brd);
lbTracefields.Items.Add(gridInternal);
if (!IsFocusSet)
{
cmb.Focus();
IsFocusSet = true;
}
break;
default:
break;
}
}

How to implement my own SelectionChangedEventHandler in c#

I am working in silverlight and under a very strange situation that i need to implement my own SelectionChangedEventHandler handler function .The reason to do so is:
I have my situation like this :
private static Grid GenerateList(Parameter param, int LoopCount, Grid g)
{
Grid childGrid = new Grid();
ColumnDefinition colDef1 = new ColumnDefinition();
ColumnDefinition colDef2 = new ColumnDefinition();
ColumnDefinition colDef3 = new ColumnDefinition();
childGrid.ColumnDefinitions.Add(colDef1);
childGrid.ColumnDefinitions.Add(colDef2);
childGrid.ColumnDefinitions.Add(colDef3);
TextBlock txtblk1ShowStatus = new TextBlock();
TextBlock txtblkLabel = new TextBlock();
ListBox lines = new ListBox();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
scrollViewer.Content = lines;
Grid.SetColumn(scrollViewer, 1);
Grid.SetRow(scrollViewer, LoopCount);
childGrid.Children.Add(scrollViewer);
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;// This items contains 1000000,3 00000, and so on.
lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged);
// lines.SelectionChanged += new SelectionChangedEventHandler(List_SelectionChanged(lines, txtblk1ShowStatus));
lines.SelectedIndex = lines.Items.Count - 1;
Grid.SetColumn(txtblk1ShowStatus, 2);
Grid.SetRow(txtblk1ShowStatus, LoopCount);
childGrid.Children.Add(txtblk1ShowStatus);
g.Children.Add(childGrid);
return (g);
}
static void List_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("clist _SelectionChanged1");
//The problem is line below because i am "lines" and "txtblk1ShowStatus" are not in the
//scope of this function and i cannot declare them globally.
txtblk1ShowStatus.Text = lines[(sender as ListBox).SelectedIndex];
}
Here you can see that i have no access of of "lines" and "txtblk1ShowStatus" in the List_SelectionChanged(object sender, SelectionChangedEventArgs e) function. And i cannot declate the button and list globally because this function GenerateList(...) will be reused and it's just coded in c# (no xaml used).Please let me know how to do that and also explain how to do that if you have another way to do but please explain your code with detail
I think a lambda expression will help you solve your issues (you might need to edit it):
lines.SelectedIndex = 0;
lines.SelectedItem = param.Component.Attributes.Items;// This items contains 1000000,3 00000, and so on.
lines.SelectionChanged += (o,e) => {
MessageBox.Show("clist _SelectionChanged1");
txtblk1ShowStatus.Text = lines.SelectedItem.ToString();
};
lines.SelectedIndex = lines.Items.Count - 1;

FlowLayoutPanel line between rows

I am trying to build a grid of companies generated from my database.
I set my flowlayout as topdown. Is it possible to put a line between rows like this http://data.worldbank.org/country
If needed, my code posted below.
public void createLinks(string[] groupNames)
{
for (int i = 0; i < groupNames.Length; i++)
{
LinkLabel obj = new LinkLabel();
obj.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
obj.LinkColor = Color.Black;
obj.Name = groupNames[i];
obj.Text = groupNames[i];
obj.Click += delegate(object sender, EventArgs e)
{LinkLabel ss = sender as LinkLabel;
frmCompanyReport test = new frmCompanyReport(ss.Name);
test.Show();
};
flowLayoutPanel1.Controls.Add(obj);
}
}
One solution is to use a Label to act as a line. Set AutoSize to False, Height to 1, and BorderStyle to FixedSingle. Then set the Width to the same as the FlowLayoutPanel.
Something like:
public void createLinks(string[] groupNames)
{
for (int i = 0; i < groupNames.Length; i++)
{
LinkLabel obj = new LinkLabel();
obj.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
obj.LinkColor = Color.Black;
obj.Name = groupNames[i];
obj.Text = groupNames[i];
obj.Click += delegate(object sender, EventArgs e)
{
LinkLabel ss = sender as LinkLabel;
frmCompanyReport test = new frmCompanyReport(ss.Name);
test.Show();
};
flowLayoutPanel1.Controls.Add(obj);
Label line = new Label();
line.AutoSize = false;
line.BorderStyle = BorderStyle.FixedSingle;
line.Height = 1;
line.Width = flowLayoutPanel1.Width;
flowLayoutPanel1.Controls.Add(line);
}
}

How to Change Content of Button if it is a child of a grid?

I want to change content of button1 on click event of button2 . But not able to get the object of grid's child Button class which is in List<> UiList.
Please Guide me in getting the right approach to look it and solve it . And also guide that if the object is build in runtime then how to access it ?
public partial class MainPage : PhoneApplicationPage
{
List<Grid> UIList = new List<Grid>();
Grid objGrid1 = null;
Button objButton1 = null;
Button objButton2 = null;
// Constructor
public MainPage()
{
InitializeComponent();
createGrid1("grid1");
createButton2("Button2");
}
public void createGrid1(string x)
{
objGrid1 = new Grid();
objGrid1.Height = 100;
objGrid1.Name = x;
objGrid1.Width = 200;
objGrid1.Margin = new Thickness(100, 100, 0, 0);
objGrid1.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objGrid1.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objGrid1.Background = new SolidColorBrush(Colors.Orange);
createButton1("changename");
}
public void createButton1(string _name)
{
objButton1 = new Button();
objButton1.Height = 90;
objButton1.Name = _name;
objButton1.Content="Button1";
objButton1.FontSize = 20;
objButton1.Width = 190;
objButton1.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objButton1.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objButton1.Background = new SolidColorBrush(Colors.Blue);
objButton1.Foreground = new SolidColorBrush(Colors.White);
objGrid1.Children.Add(objButton1);
LayoutRoot.Children.Add(objGrid1);
UIList.Add(objGrid1);
}
public void createButton2(string _name)
{
objButton2 = new Button();
objButton2.Margin = new Thickness(240, 300, 0, 0);
objButton2.Name = _name;
objButton2.Height = 90;
objButton2.Content = "Button2";
objButton2.FontSize = 20;
objButton2.Width = 190;
objButton2.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objButton2.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objButton2.Background = new SolidColorBrush(Colors.Blue);
objButton2.Foreground = new SolidColorBrush(Colors.White);
LayoutRoot.Children.Add(objButton2);
objButton2.Click += (s, e) =>
{
int c = UIList.ElementAt(0).Children.Count;
if (c == 1)
{
//logic to change content of Button1 on click of Button2
}
};
}
}
Assuming you cannot just keep a reference to the created control, such as in a class field, you can iterate through the Children property of the Grid and find the desired Button. If there are multiple buttons, you can differentiate them using the Tag property.
Once you find it, change the contents of the button using the Content property, as discussed in the contents above.

How to populate dynamically a grid on WP7?

this is my very first program in WP7, so i have some issues.
I'm trying to populate a grid with an list of objects that has been bought by another method. Here what i made so far:
public partial class MainPage : PhoneApplicationPage
{
private List<Row> lsResult;
private Grid myGrid = new Grid();
private int i = 0;
// Constructor
public MainPage()
{
InitializeComponent();
ColumnDefinition colData = new ColumnDefinition();
ColumnDefinition colOcorrencia = new ColumnDefinition();
ColumnDefinition colSituacao = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(colData);
myGrid.ColumnDefinitions.Add(colOcorrencia);
myGrid.ColumnDefinitions.Add(colSituacao);
myGrid.ShowGridLines = true;
SolidColorBrush myBrush = new SolidColorBrush(Colors.White);
myGrid.Background = myBrush;
gridResult = myGrid;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
i = 0;
lsResult = null;
lsResult = Rastrear.Busca(txtNumber.Text);
foreach (Row r in lsResult)
{
RowDefinition rNewRow = new RowDefinition();
myGrid.RowDefinitions.Add(rNewRow);
TextBlock lblData = new TextBlock();
lblData.Text = r.Data.ToString();
lblData.HorizontalAlignment = HorizontalAlignment.Center;
lblData.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumnSpan(lblData, 1);
Grid.SetRow(lblData, i);
TextBlock lblOcorrencia = new TextBlock();
lblOcorrencia.Text = r.Ocorrencia.ToString() ;
Grid.SetColumnSpan(lblOcorrencia, 2);
Grid.SetRow(lblOcorrencia, i);
TextBlock lblSituacao = new TextBlock();
lblSituacao.Text = r.Situacao.ToString();
Grid.SetColumnSpan(lblSituacao, 3);
Grid.SetRow(lblSituacao, i);
i++;
myGrid.Children.Add(lblData);
myGrid.Children.Add(lblOcorrencia);
myGrid.Children.Add(lblSituacao);
}
gridResult = myGrid;
}
}
The method Buscar() is returning the list as it should, but when i click on the button it doesn't do anything, not even the paint to white on the constructor happens actually.
thanks in advance
You're doing some pretty shady stuff in your code behind that i'm used to seeing and should be done in xaml. Change this
gridResult = myGrid;
to
gridResult.Children.Add(myGrid);
I don't think you can just change references of static UI elements like that.

Categories

Resources