C# and WPF: Programmatic Control - c#

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.

Related

C# access Textbox of parent form from Listview control class

I created custom Listview and for usage I need to access Textbox on same Form where Listview is. Currently what I do everywhere in my Listview code is this:
Form frm = FindForm();
var text_ctl = frm.Controls.Find("Textbox1", true).FirstOrDefault() as Control;
TextBox Txt = (TextBox)text_ctl;
...
Txt.Text="Test";
But instead of repeating same code over and over I want to do It only once, like in OnCreateControl() and pass that reference to everywhere I need It in my Listview class. What is the easiest or most elegant solution for this ? Thanks for help in advance !
I complicated too much, here is what I did:
private TextBox _Txt;
public void GetTxt(TextBox ref_txt)
{
_Txt = ref_txt;
}
I run GetTxt() after Form loads, then listview class has reference to It.
alternative using property:
private TextBox _Txt;
public TextBox GetTxt
{
get { return _Txt; }
set { _Txt = value; }
}
Thanks for help, specially Sandeep. And sorry for any inconvenience, I got confused a bit...

Binding Form's Size and Location properties to Labels' Text property

I'm used to data-binding in WPF which has a complete support for it and I know that it exists but is much more limited in Windows Forms.
Just out of curiosity I wanted to do some really basic data-bindings:
bind the Size property of the current Form to a Label's Text property
do the same for the Location property
Is it possible and if yes how to implement it?
Here is how you can implement it:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Label positionOutput = new Label { Dock = DockStyle.Top };
positionOutput.DataBindings.Add("Text", this, "Location");
Label sizeOutput = new Label { Dock = DockStyle.Top };
sizeOutput.DataBindings.Add("Text", this, "Size");
this.Controls.Add(positionOutput);
this.Controls.Add(sizeOutput);
}
}
It works with Location and Size because for both the Form class provides dedicated data-binding events: LocationChanged and SizeChanged.
But with Width or Height you would not benefit from a real-time automatic update because there is no WidthChanged or HeightChanged events.

Why are my XAML controls null?

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.

Silverlight RadComboBox make whole texbox area clickable

Is it possible to make the whole text area of the RadComboBox clickable while having IsEditable=true and ReadOnly=True?
I would just set IsEditable = false but unfortunately I need it to be editable in order to display custom text when something is selected (I have it set so multiple things can be selected and present a list of the selected items). If I disable IsEditable then I lose the .Text attribute and can't set a custom text.
My two best bets would be:
1) somehow apply a style that makes the whole textbar clickable and not just the arrow
2) somehow apply custom text display when IsEditable is set to false.
Unfortunately I don't know how to do either so any help would be nice. Thanks
Edit: This would be ideal, except that we're using Silverlight and not ASP.net
http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/checkboxes/defaultcs.aspx
This is probably more realistic, just to somehow make the text area clickable so it opens the dropdown menu. Just like the ComboBox on the right, minus being able to type. http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/comboboxvsdropdownlist/defaultcs.aspx
I can think of several solutions, of varying elegance. Here is one that might be suitable to close your remaining gap between the Arrow-ToggleButton and the Text-Input-Area. And now that I think about it... maybe you can get rid of that rather smelly and fragile side-effect-piggybacking with the OpenDropDownOnFocus property (which will break as soon as a click does not change the focus owner).
Register a MouseLeftButtonDown click handler with the RadComboBox, you can choose to get all events, not only unhandled events. Then we can toggle the DropDown from there. But we don't want to interfere with the Arrow-ToggleButton, therefore we check from where the mouse click originated.
public class MyView : UserControl
{
public MyView()
{
InitializeComponent();
MouseButtonEventHandler handler = OnComboBoxClicked;
radComboBox.AddHandler( UIElement.MouseLeftButtonDownEvent, handler,
handledEventsToo: true );
}
private void OnComboBoxClicked( object sender, MouseButtonEventArgs args )
{
if (!args.Handled ||
!args.IsRoutedEventFromToggleButton(
togglebuttonAncestorToStopTheSearch: (UIElement) sender))
{
ToggleDropDown();
}
}
}
and extension methods for easier use:
public static class ControlExtensions
{
public static bool IsRoutedEventFromToggleButton(
this RoutedEventArgs args,
UIElement togglebuttonAncestorToStopTheSearch )
{
ToggleButton toggleButton = ((UIElement) args.OriginalSource)
.GetAncestor<ToggleButton>( togglebuttonAncestorToStopTheSearch );
return toggleButton != null;
}
public static TAncestor GetAncestor<TAncestor>(
this DependencyObject subElement,
UIElement potentialAncestorToStopTheSearch )
where TAncestor : DependencyObject
{
DependencyObject parent;
for (DependencyObject subControl = subElement; subControl != null;
subControl = parent)
{
if (subControl is TAncestor) return (TAncestor) subControl;
if (object.ReferenceEquals( subControl,
potentialAncestorToStopTheSearch )) return null;
parent = VisualTreeHelper.GetParent( subControl );
if (parent == null)
{
FrameworkElement element = subControl as FrameworkElement;
if (element != null)
{
parent = element.Parent;
}
}
}
return null;
}
}
I ended up finding a multiselectcombobox that someone else implemented here:
http://www.telerik.com/support/code-library/a-multiselect-combobox
I didn't need the whole combobox itself since we already had one implemented so I just looked at how the person was displaying a custom message while the combo box IsEditable was set to false.
After looking at that code for a while and seeing how I can make it work for me, I put
<ucControls:RadComboBox.SelectionBoxTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text,ElementName=RadCombo}" />
</DataTemplate>
</ucControls:RadComboBox.SelectionBoxTemplate>
inside the XAML of our own custom MultiSelectComboBox. (RadCombo being the name of the particular control that I wanted the Text to be linked to)
<ucControls:RadComboBox
x:Name="RadCombo"
Text=""
........
<ucControls:RadComboBox.SelectionBoxTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text,ElementName=RadCombo}" />
</DataTemplate>
</ucControls:RadComboBox.SelectionBoxTemplate>
.......
</ucControls:RadComboBox>
Using the built in SelectionBoxTemplate, this basically just added a TextBlock overlay, and the content was bound to the RadComboBox's own Text, so when we would set the Text of the RadComboBox, the TextBlock would update itself.
This was the most effective way for us to do it because it required minimal code changes, and no structure changes since we already had all the code in place for checking boxes and setting a custom text.
Hope this helps someone, best of luck!

Setting the value of objects in XAML from the .xaml.cs file

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;

Categories

Resources