I'm finding myself coding C3 for the first time, and using Visual Studio for the first time in a looong time.
I'm creating a user control that allows for picking a file/folder etc, for making that kindof control easier to implement in the future. However whenever I drag the control unto any form, Visual Studio crashes instantly. I have tried rebuilding the entire solution several times.
The error seems to only happen when creating public variables in the control...
Does anyone know how to get around this?
Code is work in progress.... ;)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BackupReport.tools
{
public partial class pathchooser : UserControl
{
#region "Datatypes"
public enum DLG { Folder, FileSave, FileOpen };
#endregion
#region "public properties"
public DLG Dtype
{
get
{
return this.Dtype;
}
set
{
this.Dtype = value;
}
}
public string labelText
{
get
{
return this.labelText;
}
set
{
this.labelText = value;
label1.Text = this.labelText;
}
}
#endregion
#region "Constructor"
public pathchooser()
{
InitializeComponent();
this.Dtype = DLG.Folder;
this.labelText = "Source:";
label1.Text = this.labelText;
}
#endregion
private void browse_button_Click(object sender, EventArgs e)
{
switch (this.Dtype)
{
case DLG.Folder:
if (fbd.ShowDialog() == DialogResult.OK)
{
path_textbox.Text = fbd.SelectedPath;
}
break;
case DLG.FileSave:
break;
case DLG.FileOpen:
break;
default:
break;
}
}
}
}
Any help would be appreciated.
also I'm not sure it matters, but I'm using VS11 beta.
//Martin
public DLG Dtype
{
get
{
return this.Dtype;
}
set
{
this.Dtype = value;
}
}
You have a property referring to itself, and thus calling its own getter and setter inside (respectively) the getter and setter. Something more appropriate would either be to either have empty accessors:
public DLG DType{get; set;}
or to have accessors referring to private variables:
private DLG dtype;
public DLG Dtype
{
get
{
return this.dtype;
}
set
{
this.dtype = value;
}
}
I think your properties are causing a StackOverflowException because the getters and setters invoke themselves in an endless loop (Dtype -> Dtype -> Dtype ...).
Try this code instead:
private string labelText;
public DLG Dtype { get; set; }
public string LabelText
{
get { return this.labelText; }
set
{
this.labelText = value;
label1.Text = value;
}
}
Related
Question: I have a Winform C# project that changes the tool tip text of a user control tool tip when passed from a host project. I need to pass font size as a variable, but dont know where to make the changes. I have tried a plethora of solutions online and am stuck with this implementation. Any help in this direction will be really appreciated.
What I have so far:
I have a C# user Control project where i have set a property to set the tool tip text to change to user specified value in my UC_ToolTipButton project, where the contents of the project are as below:
UC_ToolTipButton.cs
using System.Windows.Forms;
namespace UC_ToolTipButton
{
public partial class UC_ToolTipButton : UserControl
{
public string TT_Message
{
get{
return ToolTip_Message.GetToolTip(btnTT);
}
set{
ToolTip_Message.SetToolTip(btnTT, value);
}
}
public UC_ToolTipButton()
{
InitializeComponent();
}
}
}
In my designer file, I have placed a button (btnTT) on which I have put a tool tip (ToolTip_Message).
When I compile this User Control Forms project, it works fine and creates a dll file.
Upon importing this file in a project TryButtonTooltip, where I have the file TryTooltipForm.cs with the following content
using System.Windows.Forms;
namespace TryButtonToolTip
{
public partial class TryToolTipForm : Form
{
public TryToolTipForm()
{
InitializeComponent();
uC_TTMessage.TT_Message = #"Hi";
}
}
}
Set OwnerDraw on ToolTip to true, in ToolTip's Draw event set the desired font, then in Popup event measure and set the size of your ToolTip, as is explained in the example here.
For example like this (untested):
public partial class UC_ToolTipButton : UserControl
{
public string TT_FontFamily { get; set; }
public float TT_FontSize { get; set; }
public string TT_Message
{
get
{
return ToolTip_Message.GetToolTip(btnTT);
}
set
{
ToolTip_Message.SetToolTip(btnTT, value);
}
}
public UC_ToolTipButton()
{
InitializeComponent();
TT_FontFamily = "Tahoma";
TT_FontSize = 10;
ToolTip_Message.OwnerDraw = true;
ToolTip_Message.Draw += new DrawToolTipEventHandler(TT_Draw);
ToolTip_Message.Popup += new PopupEventHandler(TT_Popup);
}
private void TT_Popup(object sender, PopupEventArgs e)
{
using (Font f = new Font(TT_FontFamily, TT_FontSize))
{
e.ToolTipSize = TextRenderer.MeasureText(ToolTip_Message.GetToolTip(e.AssociatedControl), f);
}
}
private void TT_Draw(System.Object sender,
System.Windows.Forms.DrawToolTipEventArgs e)
{
e.DrawBackground();
e.DrawBorder();
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (Font f = new Font(TT_FontFamily, TT_FontSize))
{
e.Graphics.DrawString(e.ToolTipText, f, SystemBrushes.ActiveCaptionText, e.Bounds, sf);
}
}
}
}
I'm using a treeview inside my informs application. When I load up nodes with a lot of text, the text gets chopped at 12 characters. How do I keep this from happening?
Font being used:
Microsoft Sans Serif, 12pt, style=Bold
I have tried using plain fonts with no luck.
Here is my code (I've overridden the treenode with another class):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace Repetrel
{
public class ActionObjectTreeNode: TreeNode
{
public string fileName = null;
private ActionObject actionObject = new ActionObject();
public string Text {
get { return base.Text; }
set {
if (value.Equals(base.Text) == false && base.Text!="")
{
Trace.WriteLine("error detected");
}
base.Text = value;
}
}
public ActionObject ACTIONOBJECT
{
get
{
return actionObject;
}
set
{
actionObject = value;
if (value == null && TREENODETYPE != TreeNodeType.Project) {
System.Diagnostics.Trace.WriteLine("null assigned to actionobject");
}
}
}
public TreeNodeType TREENODETYPE { get; set; }
public TreeNodeType LOCKEDNODETYPE { get; set; }
public DrillActionGroup ACTIONPROPERTIES { get; set; }
public ActionObjectTreeNode()
{
}
public ActionObjectTreeNode(string text)
{
this.Text = text;
}
public ActionObjectTreeNode(ActionObject actionObject)
{
if (actionObject != null)
{
this.Text = actionObject.TEXT;
this.ACTIONOBJECT = actionObject;
}
}
public bool guidMatch(string _guid)
{
return ACTIONOBJECT.getGuid().Equals(_guid);
}
}
}
Set the font size property value of the treeview higher than the font size you set programmatically.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.treenode.nodefont?view=netframework-4.8
The text of a node may be truncated when you programmatically set the Font property of the node to the Bold value.
You need add an empty string to the text after you programmatically set the Font property of the node to the Bold value.
eg:
treeView1.Nodes[0].NodeFont = new System.Drawing.Font("Microsoft Sans Serif", 12pt, System.Drawing.FontStyle.Bold);
treeView1.Nodes[0].Text += string.Empty;
Apparently I was cropping the text inside the treeview itself. Problem solved. Thanks for all the help!
I have this very simple code which, as far as I can see, I'm using all over my program where it works.
using CompetitionManager.DataAccess;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Windows;
using System.Windows.Input;
namespace CompetitionManager.ViewModel.CompetitionSetup
{
public class AthleteListViewModel : ViewModelBase
{
private Athlete selectedAthlete;
public ICommand AddAthleteCommand { get; private set; }
public AthleteListViewModel()
{
AddAthleteCommand = new RelayCommand(() => ExecuteAddAthleteCommand());
}
public Athlete SelectedAthlete
{
get
{
return selectedAthlete;
}
set
{
if (selectedAthlete == value)
return;
selectedAthlete = value;
RaisePropertyChanged("SelectedAthlete");
}
}
private void ExecuteAddAthleteCommand()
{
try
{
MessageBox.Show(SelectedAthlete.Id.ToString());
}
catch (System.Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
}
I tried binding the SelectedValue of the ComboBox to SelectedAthlete but nothing happened so I decided to try using the code behind.
If I print out the value of SelectedAthlete as it is being set, i.e. after the selectedAthlete = value line then I get a correct value but when it's time for the ICommand to kick in selectedAthlete has been set to null.
I set the value of SelectedAthlete in the code behind of a user control like so where cbAthlete is a ComboBox.
using CompetitionManager.DataAccess;
using CompetitionManager.ViewModel;
using System.Windows.Controls;
namespace CompetitionManager.View.CompetitionSetup
{
public partial class AthleteListView : UserControl
{
private ViewModelLocator locator = new ViewModelLocator();
public AthleteListView()
{
InitializeComponent();
}
private void cbAthlete_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
locator.AthleteList.SelectedAthlete = (Athlete)cbAthlete.SelectedValue;
}
}
}
Like I said before, I do this in many places in my program and it works fine but in this case there is something I'm not seeing that's wrong. Any help greatly appreciated. If I set the value of selectedAthlete in the constructor then it's not set as null. If I initialize it in the constructor, i.e. selectedAthlete = new Athlete(); then it's the same story.
Any and all help greatly appreciated.
It would help if you posted the XAML, but my guess is you forgot to set the DataContext based on what's posted so far.
I'm creating a simple application that takes a URL and a String and create the code for a hyperlink.
Here is my HyperLink Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LinkIt_
{
class HyperLink
{
private string url;
private string text;
public HyperLink()
{
}
public HyperLink(string url,string text)
{
this.Website = url;
this.Text = text;
}
public String Website
{
get
{
return url;
}
set
{
if (String.IsNullOrEmpty(value))
{
throw new ArgumentNullException("Must have URL!");
}
this.url = value;
}
}
public String Text
{
get
{
return text;
}
set
{
if (String.IsNullOrEmpty(value))
{
throw new ArgumentNullException("Must have Text!");
}
this.text = value;
}
}
public string addPoint()
{
return String.Format("<li>", url) + text + "</li>";
}
public override string ToString()
{
return String.Format("",url) + text + "" ;
}
}
}
Here is my Form Class
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;
namespace LinkIt_
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
HyperLink link;
try
{
if (chkPoint.Checked)
{
txtDisplay.Text = "";
link = new HyperLink(txtLink.Text, txtText.Text);
txtDisplay.Text = link.addPoint();
}
else
{
txtDisplay.Text = "";
link = new HyperLink(txtLink.Text, txtText.Text);
txtDisplay.Text = link.ToString();
}
}
catch (ArgumentNullException msg)
{
MessageBox.Show(msg.Message);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
txtDisplay.Text = "";
txtLink.Text = "";
txtText.Text = "";
}
}
}
My Question:
How do I make sure that I don't create a partially initialized object?
If my code need correcting, Could someone help me ?
You could refactor your code to use properties with decreased accessor visibility.
This way the HyperLink objects can not be altered from outside the class (this is often a preferable attribute for data structures).
For example you could do something like this:
class HyperLink
{
public String Website{get; private set;}
public String Text {get; private set;}
public HyperLink(string url,string text)
{
if(string.isNullOrEmpty(url) || string.IsNullOrEmpty(text))
throw new ArgumentNullException("no partially intialized object allowed");
this.Website = url;
this.Text = text;
}
public string AddPoint()
{
return String.Format("<li>", url) + text + "</li>";
}
public override string ToString()
{
return String.Format("",url) + text + "" ;
}
}
Update to answer question in comments
Yes, it is perfectly reasonable to use the Getter/Setter from within the same object or class.
However, I advise to improve your usage of String.Format to the following:
String.Format("{1}",this.Link, this.Text);
I have designed a custom panel which can expand or collapse form at run time.
When I change its height from custom designed task, it does not update it.
Code of my control class:
using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;
[Designer(typeof(MyControlDesigner))]
public partial class ExpandCollapsePanel : UserControl
{
private bool flag = false;
private Size size;
public int usrVerticalSize;
public ExpandCollapsePanel()
{
InitializeComponent();
}
[DefaultValueAttribute(true)]
public int SetVerticalSize
{
get
{
return usrVerticalSize;
}
set
{
usrVerticalSize = value;
}
}
Code of taskpanedesign class:
namespace ExpandCollapseFormLibrary
{
class CustomDialogue : ControlDesigner
{
private DesignerActionListCollection actionLists;
public override DesignerActionListCollection ActionLists
{
get
{
if (actionLists == null)
{
actionLists = new DesignerActionListCollection();
actionLists.Add(new MyActionListItem(this));
}
return actionLists;
}
}
}
internal class MyActionListItem : DesignerActionList
{
public MyActionListItem(ControlDesigner owner) : base(owner.Component)
{
}
public override DesignerActionItemCollection GetSortedActionItems()
{
var items = new DesignerActionItemCollection();
//items.Add(new DesignerActionTextItem("Hello world", "Misc"));
items.Add(new DesignerActionPropertyItem("Checked", "Vertical Drop Down Size"));
return items;
}
public int Checked
{
get { return ((ExpandCollapsePanel)base.Component).SetVerticalSize; }
set { ((ExpandCollapsePanel)base.Component).SetVerticalSize = value; }
}
}
}
When I change the value the Form1(where drag and dropped) designed class keep it permanently.
the SetVerticalSize property value of your custom pane's is really changed, but the problem is that the designer host does not know about it at all. To notify the designer host about your custom pane changing you should implement something like this (I suggest you read the IComponentChangeService MSDN article for more details):
int usrVerticalSize;
[DefaultValue(true)]
public int SetVerticalSize {
get { return usrVerticalSize; }
set {
FireChanging(); //changing notification
try {
usrVerticalSize = value;
}
finally { FireChanged(); } //changed notification
}
}
void FireChanging() {
IComponentChangeService service = GetComponentChangeService();
if(service != null)
service.OnComponentChanging(this, null);
}
void FireChanged() {
IComponentChangeService service = GetComponentChangeService();
if(service != null)
service.OnComponentChanged(this, null, null, null);
}
IComponentChangeService GetComponentChangeService() {
return GetService(typeof(IComponentChangeService)) as IComponentChangeService;
}