I can declare a checkbox in XAML like so
<CheckBox Content="Accepted" Height="71" Name="checkBox" />
When this screen loads I want to check the data associated with the screen and set it if the box is checked, or it its not checked.
public TripDetails()
{
string yesString = "YES";
if (String.ReferenceEquals(meeting.accepted, yesString))
{
// set the checkbox
}
this.DataContext = this;
InitializeComponent();
}
What I cannot understand is how to set the checkbox declared in the XAML from within my cooresponding xaml.cs file.
Could somebody please advise what should go where my
// set the checkbox
is.
Many Thanks,
-Code
Unless I'm missing something...since you've named the CheckBox "checkBox", it should just be
this.checkBox.IsChecked = !this.checkBox.IsChecked;
Related
I have a XAML layout similar to this:
<Grid>
<TextBox x:Name="inputTextBox" LostFocus="inputTextBox_LostFocus" TextChanged="inputTextBox_TextChanged" GotFocus="inputTextBox_GotFocus" />
<ComboBox x:Name="inputComboBox" SelectionChanged="inputComboBox_SelectionChanged">
<ComboBoxItem IsSelected="True">10</ComboBoxItem>
<ComboBoxItem>15</ComboBoxItem>
<ComboBoxItem>20</ComboBoxItem>
</ComboBox>
<ComboBox x:Name="inputComboBoxTwo" SelectionChanged="inputComboBoxTwo_SelectionChanged">
<ComboBoxItem IsSelected="True">1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
</ComboBox>
</Grid>
Pretty simple. In the codebehind C# file, I use these controls to take in a double from the TextBox, some more ints from the ComboBoxes, then I create a calculator type object with the data from the controls. I make the calculation and display the results in some other TextBlocks.
namespace TipCalc
{
public sealed partial class MainPage : Page
{
Calc x = new Calc();
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
//
//Appropriate event handlers from XAML controls that all call the calculation method.
//
private void calcIt()
{
x.amt = double.Parse(inputTextBox.Text);
x.cal1 = int.Parse(inputComboBox.SelectedItem.ToString());
x.cal2 = int.Parse(inputComboBoxTwo.SelectedItem.ToString());
//Send calculated values to output TextBlocks.
}
}
}
When I run this program, I hit a null pointer exception that is thrown when I attempt to access the text property of the TextBox. It turns out that all of the XAML controls are null. However, _contentLoaded is set to true and the code definition for this.IntializeComponent looks correct behind the scenes.
Why are all my controls set to null when it seems like everything is working correctly? Is there a way to manually initialize them if they aren't correctly being initialized automatically? Am I doing anything wrong?
the code run like:
Calc x = new Calc();
this.InitializeComponent();
Calc() was first than InitializeComponent(), but InitializeComponent() create your controls.
you can change to:
Calc x;
public MainPage()
{
this.InitializeComponent();
x = new Calc();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
I have the same problem with some of my TextBox controls when the class initializes. What I did to solve this is not the real and perfect solution because not all the controls (TextBox, ComboBox, RadioButton, etc) are null when the class is running, and there's something happening in my code or my app or my VS that I'm missing or doing wrong.... But at least is working fine now. I hope is useful to you:
if(TextBox1 == null)
{
//I'm re-initializing the control because is null
TextBox1 = new TextBox();
}
For your code it should be something like this:
if(inputTextBox == null)
{
inputTextBox.Text = new TextBox();
}
x.amt = double.Parse(inputTextBox.Text);
I hope this 'solution' is good enough for you. And for my poor English I apologize if I have mistakes, is not my native language.
I try to understand data bindings in WPF and I could already bring some tests to work. But I'm stuck tight now. :(
For better organization I want to split my code into more classes and bind elements of the same Window to different classes (actually to properties of different classes).
I think I have to set the DataContext of my Window to "this" (The window itself) and use the Binding Path to specify the property to use.
DataContext = this;
-
<Label Content="{Binding Path=_printSettings.CopyCount}"/>
So f.e. I want to bind to CopyCount wich is a property returning a string. That property belongs to the instance in the private field _printSettings of the current window. And _printSetting implements the INotifyPropertyChanged and notifies in a twoway principle.
But the label is empty during design and runtime...
I also noticed that no default values are set in the designer in my previous tests. Does anyone know an implementation? If possible without the use of a fallback value.
-MainWindow.xaml.cs
<Label Content="{Binding ElementName=MainWindow,Path=PrintSettings.CopyCount, FallbackValue=[0]}">
-MainWindow.cs
private PrintSettings _printSettings = new PrintSettings();
public PrintSettings PrintSettings {
get {
return _printSettings;
}
}
public MainWindow()
{
DataContext = this;
}
PrintSettings.cs
private int _copyCount = 1;
//Copy count
public string CopyCount
{
get {
return "" + _copyCount;
}
}
-
EDIT:
added more code again
Binding works against/through public properties. _printSettings is not a property. The Visual Studio "Output" window can show any binding errors you have.
_printSettings and CopyCount should be public.
If it doesnt help, then in xaml Set window Name and binding will look like this
<Label Content="{Binding ElementName=YourWindowName,Path=_printSettings.CopyCount}"/>
or
<Label Content="{Binding ElementName=YourWindowName,Path=DataContext._printSettings.CopyCount}"/>
In my program's main window I have a TreeView and a ContentPresenter. The display of the ContentPresenter is determined by what node is selected in the TreeView.
The name of one of my nodes is allowed to be changed by the user via contentMenu. All the user has to do is right click the node and select the new name out of the choices. The ContentPresenter is supposed to have a null display until the user chooses a name for the node.
The problem occurs when a new name is selected from the contentMenu. The ContentPresenter's display changes, like it should, but only after the user selects a different node (changing the display), and then re-selects the original node.
How do I make it so that the display on the ContentPresenter changes right when the TreeView node's name is changed?
TreeViewViewModel:
public class TreeViewViewModel : PropertyChangedBase
{
public TreeViewViewModel()
{
Node = new Node() { NodeName = "Blank", NodeDataModel = new NodeModel(),
Commands = { new Command(nodeType_name1), new Command(nodeType_name2) } };
}
//These functions call to the NodeName property in the TreeView's Data Model
private void nodeType_name1()
{
Node.NodeName = "Name1";
}
private void nodeType_name2()
{
Node.NodeName = "Name2";
}
}
XAML for MainWindow:
<!-- Tree view items & Functions -->
<TreeView Name="Tree_One" ItemsSource="{Binding DataTree.Data}" ... >
<TreeView.Resources>
<SolidColorBrush Color="LightSkyBlue" x:Key="{x:Static SystemColors.HighlightBrushKey}" />
</TreeView.Resources>
</TreeView>
<!--- Left Widget -->
<ContentPresenter Content="{Binding LeftWidget}" />
MainWindowViewModel:
public class MainWindowViewModel : PropertyChangedBase
{
private TreeViewViewModel _dataTree;
public MainWindowViewModel()
{
_dataTree = new TreeViewViewModel();
}
public TreeViewViewModel DataTree { ... }
//This function is in charge of changing the display of the ContentPresenter
// I think that my problem can probably be solved by doing something here
public void ChangeViews()
{
if (_dataTree.SelectedItem is Node)
{
var _node = _dataTree.SelectedItem as Node;
var nodeViewModel = new NodeViewModel(_node.NodeDataModel);
if (_node.NodeName== "Unknown")
LeftWidget = null; //This is the Content Presenter **
if (_node.NodeName == "Name1")
{
LeftWidget = nodeViewModel;
}
if (_node.NodeName == "Name2") {...}
}
}
}
Duh, thats a alot of code and its pretty difficult to understand what you up to since you seem to have controls in your ViewModel.
Or at least it looks to me that you have them in ViewModel. That is not very MVVM-alike my friend. :)
"The problem occurs when a new name is selected from the contentMenu. The ContentPresenter's display changes, like it should, but only after the user selects a different node (changing the display), and then re-selects the original node."
The property changed is not being fired because the new selected value is equal to the old one.
Pretty obvious, right?... no property was actually changed
But why do you want the ContentPresenter to update itself with the value that it already has?
You said when you select a node the ContentPresenter displays it properly and when you re-select the same the ContentPresenter is not doing anything.
Its not doing anything because it think it doesnt need to. Which is true.
So the question is why would you make ContentPresenter force to refresh on each value no matter if old value is the same as new one?
Though if you want to hack/trick a little bit, you can always set ContentPresenter's Content to null before you assign another value. :)
However, post us more code and we will be able to provide you a better solution to your issue.
I was able to fix this issue by calling ChangeViews(); in my MainWindowViewModel from my TreeViewViewModel. I did this by using a delegate property in the TVVM, and adding it to my MWVM. By doing this, the display is updated whenever ChangeViews(); is called.
This is the answer that I used.
I know I am missing something here and I could use a pointer. Within a project I have an expander control when this control is clicked it makes a RIA call to a POCO within my project to retreive a second set of data. I am using the SimpleMVVM toolkit here so please let me know if I need to expand on any additional areas.
Within the xaml the expander is laid out as
<toolkit:Expander Header="Name" Style="{StaticResource DetailExpanderSytle}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<ei:CallMethodAction
TargetObject="{Binding Source={StaticResource vm}}"
MethodName="showWarrantNameDetail"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Vertical">
<sdk:DataGrid AutoGenerateColumns="true" ItemsSource="{Binding NameResult}" AlternatingRowBackground="Gainsboro" HorizontalAlignment="Stretch" MaxHeight="200">
</sdk:DataGrid>
<local:NameContainer DataContext="{Binding}" />
</StackPanel>
</toolkit:Expander>
I am using the expression Dll coupled with Simple MVVM to get at the methods in the view model vs commands.
Within the view model I have the following code
public void showWarrantNameDetail()
{
//set flags
IsBusy = true;
CanDo = false;
EntityQuery<WarrantNameDataView> query = App.cdContext.GetWarrantNameDataViewsQuery().Where(a => a.PrimaryObjectId == Convert.ToInt32(RecID));
Action<LoadOperation<WarrantNameDataView>> completeProcessing = delegate(LoadOperation<WarrantNameDataView> loadOp)
{
if (!loadOp.HasError)
{
processWarrantNames(loadOp.Entities);
}
else
{
Exception error = loadOp.Error;
}
};
LoadOperation<WarrantNameDataView> loadOperation = App.cdContext.Load(query, completeProcessing, false);
}
private void processWarrantNames(IEnumerable<WarrantNameDataView> entities)
{
ObservableCollection<WarrantNameDataView> NameResult = new ObservableCollection<WarrantNameDataView>(entities);
//we're done
IsBusy = false;
CanDo = true;
}
When I set a break on the processWarrantName I can see the NameResult is set to X number of returns. However within the view the datagrid does not get populated with anything?
Can anyone help me understand what I need to do with the bindings to get the gridview to populate? Other areas of the form which are bound to other collections show data so I know I have the data context of the view set correctly. I've tried both Data context as well as Items Source and no return?
When I set a break on the code the collection is returned as follows so I can see that data is being returned. Any suggestions on what I am missing I would greatly appreciate it.
With regards to the page datacontext I am setting it in the code behind as follows:
var WarrantDetailViewModel = ((ViewModelLocator)App.Current.Resources["Locator"]).WarrantDetailViewModel;
this.DataContext = WarrantDetailViewModel;
this.Resources.Add("vm", WarrantDetailViewModel);
Thanks in advance for any suggestions.
Make ObservableCollection<WarrantNameDataView> NameResult a public property of your ViewModel class. Your view will not be able to bind to something that has a private method scope (or public method scope, or private member scope).
//declaration
public ObservableCollection<WarrantNameDataView> NameResult { get; set }
//in the ViewModel constructor do this
NameResult = new ObservableCollection<WarrantNameDataView>();
//then replace the original line in your method with:
//EDIT: ObservableCollection has no AddRange. Either loop through
//entities and add them to the collection or see OP's answer.
//NameResult.AddRange(entities);
If processWarrantNames gets called more than once, you might need to call NameResult.Clear() before calling AddRange() adding to the collection.
Phil was correct in setting the property to public. One note I'll add is there is no AddRange property in SL or ObservableCollection class that I could find. I was able to assign the entities to the OC using the following code
private ObservableCollection<WarrantNameDataView> warrantNameResult;
public ObservableCollection<WarrantNameDataView> WarrantNameResult
{
get { return warrantNameResult; }
set
{
warrantNameResult = value;
NotifyPropertyChanged(vm => vm.WarrantNameResult);
}
}
and then within the return method
WarrantNameResult = new ObservableCollection<WarrantNameDataView>(entities);
This worked and passed to the UI the collection of data.
I'm learning WPF, and seem to have found something a little odd, which I can't find the reason to anywhere I've searched.
I have a window with one checkbox on it called "chkTest". I have it set to be true by default.
The following code is what I don't understand. Basically I'm trying to set the "chkTest" control to a control I create on the fly. The message box displays the value I set in code, but the control on the window is still set to be true.
Can someone explain the process behind this?
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
CheckBox chk = new CheckBox();
chk.IsChecked = false;
this.chkTest = chk;
MessageBox.Show(chk.IsChecked.Value.ToString());
}
}
Thanks
This is because you're fooling the DependencyProperty system by doing this - remember, getters/setters of DP properties work differently than regular properties. The UI has a trigger on the IsChecked property, but you replace the whole object. Since you didn't actually change IsChecked on the visible checkbox, the trigger doesn't fire and the UI isn't updated.
Here's one way to go about it. First, you give a name to your main Grid - say, LayoutRoot:
<Grid x:Name="LayoutRoot">
<CheckBox x:Name="chkTest" IsChecked="True"></CheckBox>
</Grid>
Then, you say:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
CheckBox chk = new CheckBox();
chk.IsChecked = false;
LayoutRoot.Children.Remove(chkTest);
LayoutRoot.Children.Add(chk);
}
}
And you're done.