I am creating a View Controller that records the Phone Number or Email adress of the user, and I want the placeholder of the textfield to change when they select either the "Phone" button, or the "Email" button.
This is just the button that is supposed to change the placeholder
void PhoneSelectBtn(object sender, EventArgs e)
{
EmailPhoneBox.AttributedPlaceholder = new NSAttributedString("Phone");
}
and every time I run the application, it crashes and this is the error that I get:
Objective-C exception thrown. Name: NSUnknownKeyException Reason: [<UIViewController 0x7f813ec3b870> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key EmailPhoneBox.
Native stack trace:
I have tried other options, such as using a segmented control (obviously it is a little different then setting up a button), and I get the same result. I have changed button methods, classes, and the same result occurs every single time. There are no unnecessary events lingering that aren't attached to anything either. Out of ideas. If one could explain step by step what to do, that would be great. I am sure that it isn't a hard thing to do, but I am just learning, and am finding it hard to find applicable documentation on small things like this. Thanks, Josh
It seems that just like with many other Xamarin features which seem like they should be added but aren't, this one needs a custom renderer.
See this link for more.
Another option is
Set the placeholder string to your Editor's Text in Xaml Then in Code behind file:
InitializeComponent();
var placeholder = myEditor.Text;
myEditor.Focused += (sender, e) =>
{
// Set the editor's text empty on focus, only if the place
// holder is present
if (myEditor.Text.Equals(placeholder))
{
myEditor.Text = string.Empty;
// Here You can change the text color of editor as well
// to active text color
}
};
myEditor.Unfocused += (sender, e) =>
{
// Set the editor's text to place holder on unfocus, only if
// there is no data entered in editor
if (string.IsNullOrEmpty(myEditor.Text.Trim()))
{
myEditor.Text = placeholder;
// Here You can change the text color of editor as well
// to dim text color (Text Hint Color)
}
};
Related
I have a RichTextBox. I'm working on changing the SelectionBackColor only of the selected text.
Then, I have a ToolStripMenuItem(let's call it 'buttonA' for now) which is responsible to change the SelectionBackColor of the selected text. The problem I'm facing is after I click buttonA, the background color of the selected text in the RichTextBox can be successfully done. However, when I add some other characters or text right after the changed background color text, it doesn't use the default background color. Instead, it continues to use the same background color as assigned from buttonA, which I don't want to happen.
At first, I thought that my start index and end index of the selected text was problematic. But, I don't think there's any problems in its codes. Below shows the code example:
SolidBrush textBgCol; //a variable to keep color
this.richTextBox1.Select = this.richTextBox1.SelectionStart, this.richTextBox1.SelectionLength;
this.richTextBox1.SelectionBackColor = Color.FromArgb(textBgCol.Color.A, textBgCol.Color.R, textBgCol.Color.G, textBgCol.Color.B);
One of my efforts was to change the SelectionBackColor to default in the KeyDown event of richTextBox1. However, the background color of the new or successive characters and text were still the same as assigned from buttonA. Below shows the code example:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
this.richTextBox1.SelectionBackColor = default;
}
I've also tried to refer to this but, I don't think it helps me to solve my case here.
Other than that, just to confirm that my richTextBox1's SelectionStart and SelectionLength were okay, I've even referred to these: ref1, ref2, and ref3.
May I know any other workarounds for this please? Or, were there anything inside my codes that I've missed?
Based on comment by #Jimi:
I just need to change the codes in my richTextBox1's KeyDown event handler to:
if(richTextBox1.SelectionBackColor != richTextBox1.BackColor)
{
richTextBox1.SelectionBackColor = richTextBox1.BackColor;
}
Below shows the demo:
Thanks!
I am working with c#.
My goal is to be able to add an integer to a free response textbox. Allow me to explain.
I have a textbox called (Red,Green,Blue). Each color will be replaced using the Replace(); method.
Like this:
private void RedTextBox_TextChanged(object sender, EventArgs e) //ActualFogColor is Result
{
string ActualColorFog = "game.Lighting.FogColor = Color3.new(Red,Green,Blue)";
string Red = RedTextBox.Text;
string FogColorRed = ActualColorFog.Replace("Red", Red);
ActualColorFogScript.Text = FogColorRed;
}
This repeats for all other colors and it works fine. The problem I have is that I have a brightness button that when you click it, it adds 1 to the inputted number, but of course I had to convert it into an integer. It is basically initial + 1 = the new color. Replace Initial with new color and print that on the textbox.
Unfortunately i can't do
public partial class main : Form
{
int red = Convert.ToInt32(RedTextbox.Text); }
This is at the very top of the code which is why when doing this, it doesn't recognize RedTextBox.
The reason I am trying to assign the integer to the textbox is so that when the " RedTextBox.Text = '5' " It will take that 5 and add 1(by a button) which then prints the sum which I set equal to Red in string ActualColorFog = "game.Lighting.FogColor = Color3.new(Red,Green,Blue)";
I hope this make sense to you all, if you are confused on my plan, please leave your question.
I'd suggest you take one step back and think about the usability of your inputs. What I mean if you allow the user to freely enter the text, you have to tackle the input values like negative numbers, literals, numbers outside of the range (0-255 I presume), non-integer input, etc. Furthermore it would be nice if the user can use mouse scroll to increase/decrease the value. Perhaps a numeric up-down would be solution for your problem? It's not a standard control but there are enough implementations of it freely available.
Should you insist on using the text input, do the following:
define 3 integer member variables in your code for the components.
provide the Changed event handler for each textbox where you int.TyParse the input, check the ranges and if all goes well and update the respective member variable if it differs from the new value
probably add mouse scroll event handler
your button's Click event handler will update the member variables and the text values in the textboxes
A nicer solution would be to use the dependency properties instead of member variables, the content of the textboxes is bound to the dependency variables one way and the textboxes' Checked event handler does the parsing.
I am not getting into that if your method is good or not but just how to solve this problem.
As i can see, ideal for you would be that you can assign int red = Convert.ToInt32(RedTextbox.Text); and you cannot because it is at top of your code?
It is not recognizing because that part of code is accessed before RedTextBox is even initialized. Solution for this is to put int red = -1; and then
public main() //Your form constructor
{
InitializeComponents();
// I guess you somehow add some value to RedTextbox on form
showing so it need to be before assigning red variable
red = Convert.ToInt32(RedTextbox.Text); //It is important to be after Initializecomponents()
}
I want to click a button and change its text's color and message properties.
I got the button to change its color, but I need to change one of its text's colors.
private void TurnGreen(Button button)
{
ColorBlock colors = button.colors;
colors.normalColor = Color.green;
button.colors = colors;
}
The above code changed the button's color which I liked, but I would rather change the button's text. Note however that my button has two text-childs. The text I want to change has a name of "Ore".
Haven't done Unity for ages, so my knowledge is bit rusty.
Make sure using System.Linq; is set in your script.
// Considering that "button" is the one on which you clicked.
// By definition, we have 2 Text children (for single Text, we
// could use button.GetComponentInChildren<Text>().color directly, as it returns single element.
var oreText = button.GetComponentsInChildren<Text>().FirstOrDefault(o => o.name == "Ore"); // Unity allows same naming...
// I had 2 Text components initially returned: Ore and Wood.
// Got the Ore text component with FirstOrDefault. Now check it really exists and set color.
if (oreText != null) // Long way to compare. For illustration.
{
oreText.color = Color.green;
}
// Also, if "Ore" button really exists, you can directly set it from "Single" method:
// button.GetComponentsInChildren<Text>().Single(o => o.name == "Ore").color = Color.green;
A better way to do this might be to identify the text component in question from the editor (assuming your button is a Prefab), rather than iterating through the components via Linq. If you do it that way, it's scales a little better if you want to use that type of behavior on other components/buttons but don't want to have to change the Linq search text each time.
To do this, create a new field like this:
public Text textToChange;
Then drag the component in question form your button into your component script from the editor, then in code do this:
textToChange?.color = Color.green;
And then boom, you're done...the '?.' also checks for null for you without the if block.
I have a custom WPF control that inherits from RichTextBox. I'd like to be able to modify the FlowDocument of the richtextbox whenever the text is changed. For demonstration, let's say that we have this:
<MyCustomRichTextbox>
<FlowDocument>
<Paragraph>This is the first paragraph</Paragraph>
<Paragraph>And this is the second</Paragraph>
</FlowDocument>
</MyCustomRichTextbox>
and whenever the text is changed (e.g. someone types in the control), the entire containing paragraph is colored red.
It seems to me that two things need to happen in order to achieve this:
I need to somehow get the block that contains the changed text out of MyCustomRichTextbox.Document.Blocks
I need to modify that block
Unfortunately, the OnTextChanged method doesn't provide a way to get the Block that changed. I was able to use LINQ and the TextChangedEventArgs.Offset to get the block, but I'm concerned that this approach will yield unacceptable slowdowns with larger documents (since it must enumerate each block every time a character is typed). Is there a better way to get the containing paragraph?
I know I could cache a reference to the "Last modified block" and check if it's still the one being modified, but that wouldn't really help in a random access scenario.
If I understand your problem correctly, you want to highlight the containing Paragraph of the current selection (the current position of the caret). So it's obviously that you have to get the containing Paragraph each time the Selection changes. Then you can just change the Foreground to Brushes.Red. Fortunately that the containing Paragraph seems to be referenced by the TextPointer and the process of finding it is nearly immediate. (a TextPointer has a property called Paragraph). Here is the detailed code:
Paragraph p = null;
//Suppose rtb is the name of your RichtTextBox
private void UpdateContainingBlockState() {
if (p != rtb.Selection.Start.Paragraph){
if (p != null) p.Foreground = Brushes.Black;
p = rtb.Selection.Start.Paragraph;
if (p != null) p.Foreground = Brushes.Red;
}
}
//The SelectionChanged event handler for your RichTextBox
private void selectionChangedHandler(object sender, RoutedEventArgs e){
UpdateContainingBlockState();
}
The frequency of changing the Selection is fairly high (each time you press almost keys which can cause the selection changing). So if your document is large and you realize some poor performance while typing, it's time to switch to the next more complex code. You can also try using Threading approach (or using Task) to put the UpdateContainingBlockState() call in another thread but be careful about cross-thread access. Here I use a different approach, the idea is call the UpdateContainingBlockState() at the right time, that is when the actual selection change can jump between paragraphs. While typing normal printable characters, the selection will be always in the current paragraph (so we don't need to call UpdateContainingBlockState()) unless when you type the Enter key. Generally we will call the method when user typing a control key (arrow keys, home, end, Enter, ...). We should also call the method if the RichTextBox gets focused and if user clicks mouse on the RichTextBox. You can see that almost the typed characters won't trigger calling the method so it will improve the performance much more than the code above (of course it may be realizable only when the document is large). Here is the detailed code:
//should add this using at the beginning
using System.Runtime.InteropServices;
[DllImport("user32")]
private static extern int MapVirtualKey(int ucode, int mapType);
//The KeyUp event handler for your RichTextBox
private void keyUp_Handler(object sender, KeyEventArgs e){
if (char.IsControl((char) MapVirtualKey(KeyInterop.VirtualKeyFromKey(e.Key),0x2)))
UpdateContainingBlockState();
}
//The PreviewMouseUp event handler for your RichTextBox
private void previewMouseUp_Handler(object sender, MouseButtonEventArgs e){
//UpdateContainingBlockState();
//Calling UpdateContainingBlockState() directly will cause a small issue
//So we use this instead
Task.Run(() => Dispatcher.Invoke( () => UpdateContainingBlockState()));
}
//The GotKeyboardFocus event handler for your RichTextBox
private void gotKeyboardFocus_Handler(object sender,
KeyboardFocusChangedEventArgs e){
UpdateContainingBlockState();
}
How would you prevent the user from adding or removing lines in a TextBox? By that I mean, if I set the text in a textbox to 7 lines with some text, how can I make sure that it will always be 7 lines of text there? The user must be able to edit those lines like usual, but not remove a line entirely, and not add any new ones.
Would have to take into account both keyboard input and also things like cut and paste, etc.
Any good ideas?
Reason: I want to make a file renamer kind of like Oscar's Renamer. You give it a folder, and it loads the filenames into a textbox where you can do changes pretty much like you do in a text editor. When you are happy with your changes, you write them back. Reason for constant n lines in textbox is then of course that line n is the name of file n. Adding a new line shouldn't be allowed since you only have those files in that folder. Removing a line should also not be allowed since you would then be missing a name for a file.
Why go through the trouble of making something like this when it already exists? Well, I am curious to see if I could do it, and thought it could be a nice excercise to learn a few things along the way. Since it has some interesting problems that needs to be solved. Like this one :) There are also some features I think are lacking in that Oscar's Renamer. So... to sum up: I'm doing it to learn and to try make an even better version of it. I know fully well that I may just as well fail completely though, or just never finish it :p But that is another story. I want to learn
You have the wrong interface then for the data. In this case, you should have a fixed number of textboxes, one for each line of data. This would allow the user to modify the contents of each line, but not remove a line or add a line.
Trying to make a multi-line textbox do this will be maddening at best, since you will have to determine when a new line is added/removed and then kill the change.
Why not use a Listbox instead?
I'd probably let the user do what they want on the textbox, then add validation to show the user there is an error when they go above 7 lines (e.g. red-outline and tooltip or something). If they are under 7 lines, no problem, add them when you come to process that data.
What is the specific reason you want the always 7 lines? Like casperOne said, maybe the interface you're using isn't ideal to your needs.
One possible way of doing this is to sub-class the Textbox control and override the winProc method. This method handles all window messages pumped to the windowed control (Textbox in your case). You could monitor the use of the backspace and delete keys and carat position and discard the key strokes that attempt to remove carriage return line feed sequences. And provide the user with an interactive alert that tells them why they cannot remove entire lines.
Doing it this way gives you complete control and is the lowest level way to see all input that is coming into your Textbox control. You can intercept certain messages and discard them, the ones that you want to allow just pass them through into the base class method. Such as if the user highlights all lines and hits the delete key. There is other event handlers that you can use to intercept keyboard input but they have some limitations, the winProc will allow you to check any message directed to the control including delete, backspace copy and paste etc, mouse clicks etc.
Sample:
public class myCustomTextBox : TextBox
{
protected override void WndProc(ref Message m)
{
if (m.Msg == 770) // window paste message id
{
string clipBoardData = Clipboard.GetDataObject().GetData(DataFormats.Text).ToString();
handlePasteEvent(clipBoardData);
}
else
{
base.WndProc(ref m);
}
}
private void handlePasteEvent(string pasteData)
{
// process pasted data
}
}
Since you already have stated that this is a learning project, a see if I can do it-project, I think you should throw in some WPF into it. A listbox with a itemtemplate would solve this very nicely.
If that's out of the way, I would consider using a datagrid instead of a textbox.
Load your data in a editable DataGrid instead of a TextBox, that should make things much more simple, and also you can pick which columns are editable and which are not.
Here's an example that uses a DataGridView and simulates your textbox:
The grid lines are hidden.
The headers of columns and rows are hidden.
The background color is the same color a TexBox has.
Add a DataGridView to a form and use the following code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.AllowUserToResizeRows = false;
this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridView1.BackgroundColor = SystemColors.Window;
this.dataGridView1.BorderStyle = BorderStyle.None;
this.dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None;
this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.ColumnHeadersVisible = false;
this.dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;
this.dataGridView1.MultiSelect = false;
this.dataGridView1.RowHeadersVisible = false;
this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);
dataGridView1.DataSource = Directory.GetFiles(Environment.CurrentDirectory).Select(f => new FileEdit { FileName = Path.GetFileName(f) }).ToList();
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
dataGridView1.BeginEdit(true);
}
}
class FileEdit
{
public string FileName { get; set; }
}
}