|
sdfsdfsdfewrew3feff wrote: How connect you tabel to other tabel with relations? Usually using a number (often BIGINT) or a GUID.
If you need to remove the "-" sign from a number, consider multiplying it with -1, as opposed to converting it to a string.
Also, if it is a key-field (only there to keep relations with other records) then it should never be formatted or presented to the user at all.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I have been writing a generic factory class; in pruned-down to walk-the-dog-bits-left-out form:
public class VTBunchOLists : List<IEnumerable<T>>
{
private bool isInt;
public VTBunchOLists()
{
isInt = typeof(T) == typeof(Int32);
}
public Int32 TToInt32(T value)
{
return (Int32)Convert.ChangeType(value, typeof(Int32));
}
public void Add(T howmanyT, bool ascending = true)
{
if (isInt)
{
var range = CreateRange(1, TToInt32(howmanyT), ascending);
this.Add(range as IEnumerable<T>);
}
}
private IEnumerable<int> CreateRange(Int32 howMany, bool ascending = true)
{
var range = Enumerable.Range(start, end);
return (ascending) ? range : range.Reverse();
}
} Here's what concerns me:
1. there's no way to constrain the Type of T to certain ValueTypes ... that I've found in my research. I guess I could look at the Type of T in the 'ctor and return null, or throw an error, if the Type didn't match what I wanted to handle, but that seems less than elegant to me.
2. obviously I'll do quite a different thing (not shown in the code) if T is a double, since you can't use Enumerable.Range for producing anything but and integer Range.
3. similarly the required casting of an integer (or double) range to IEnumerable<t> to be able to add it to the collection kind of gives me an itch I can't scratch, but what do you think ?
4. (related to concern #1) while Enumerable.Range(start#int, end#int) returns a nice IEnumerable<int> ... and so the return value of the factory is an "un-evaluated" IEnumerable, since you have to use a List<doulbe> to create the range of doubles, the return value of the factory will be an "evaluated" structure. That lack of "symmetry" bothers me, but I see no way around this ... now ... except to make the factory return a List<List<T>> ... mmmm ...
Why am I doing this: well, I've already written separate implementations for Int32 and Double, and I'm curious to see what's involved in making it generic. And, there is some very fancy stuff in the current implementations (not shown in the code here) that could be consolidated.
thanks, Bill
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
modified 1-Mar-15 7:20am.
|
|
|
|
|
You can constrain it to a value type by making the whole class generic and adding the struct constraint:
public class VTBunchOLists<T> : List<IEnumerable<T>> where T : struct
{
private bool isInt;
public VTBunchOLists()
{
isInt = typeof(T) == typeof(Int32);
}
...
} (You have to use struct because ValueType isn't the root type for value types - it's just used for boxing)
And that might help a little - you can't use a where constraint on any sealed class (and all the primitives are sealed IIRC)
I have to say I don't like runtime type rejection in the constructor: I know what you mean, but it goes against my grain somewhat to force a run time error for something that should be a compile time problem!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Thanks, Griff !
I don't like Type rejection at run-time either, so 'struct will have to do.
If you have the bandwidth, I'd appreciate your reaction to a new "concern" I added to my original post: #4.
cheers, Bill
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
|
|
|
|
|
Hi Bill,
as far as I know my Roslyn yet, with it you could write a source analysis that checks whether you try to use the factory class with anything other than the value types that it is intended for and include that check into your build process, so you can get an error pre runtime. Other than that, while not very beautiful, checking in the c'tor seems to be an agreed upon solution.
- Sebastian
|
|
|
|
|
Thanks, Sebastian,
It is interesting to speculate what a "range" of structs ... where the struct is a user-defined collection of whatever Types ... might be ... but I see no practical reason to go there, and so I think that if I do use the generic version, I will do run-time Type checking; I'd rather do that than engage in any reflection.
However, it's also interesting to think about if using some new feature in Roslyn (I'm using CTP 6 Visual Studio 2015 now for testing) might somehow reduce the "cost" of reflection. I'm not aware of any meta-programming features new in Roslyn ... yet.
cheers, Bill
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
|
|
|
|
|
The core of the problem seems to be that you need to be able to add an increment to an instance of the generic type parameter T . There are various solutions for this - I tend to use some code adapted from the MiscUtil library[^]:
public static class GenericOperator<T>
{
private static readonly Func<T, T, T> _addChecked = Create<T>(Expression.AddChecked);
public static Func<T, T, T> AddChecked
{
get { return _addChecked; }
}
private static Func<T, T, TResult> Create<TResult>(Func<Expression, Expression, BinaryExpression> body)
{
try
{
Type typeT = typeof(T);
var left = Expression.Parameter(typeT, "left");
var right = Expression.Parameter(typeT, "right");
if (typeT.IsEnum)
{
Type enumType = Enum.GetUnderlyingType(typeT);
var x = Expression.Convert(left, enumType);
var y = Expression.Convert(right, enumType);
Expression op = body(x, y);
if (op.Type == enumType) op = Expression.Convert(op, typeT);
return Expression.Lambda<Func<T, T, TResult>>(op, left, right).Compile();
}
return Expression.Lambda<Func<T, T, TResult>>(body(left, right), left, right).Compile();
}
catch (InvalidOperationException ex)
{
string message = ex.Message;
return delegate { throw new InvalidOperationException(message); };
}
catch (ArgumentException ex)
{
string message = ex.Message;
return delegate { throw new InvalidOperationException(message); };
}
}
}
Since there's no way to get an instance of the generic type parameter that represents "1 ", you'll need to pass in the increment value to your Add function:
public class VTBunchOLists<T> : List<IEnumerable<T>>
{
private static readonly Func<T, T, T> AddChecked = GenericOperator<T>.AddChecked;
public VTBunchOLists()
{
}
public void Add(T startAt, T increment, int howMany, bool ascending = true)
{
IEnumerable<T> range = CreateRange(startAt, increment, howMany);
if (!ascending) range = range.Reverse();
Add(range);
}
private static IEnumerable<T> CreateRange(T startAt, T increment, int howMany)
{
T current = startAt;
for (int i = 0; i < howMany; i++)
{
yield return current;
current = AddChecked(current, increment);
}
}
}
If you want the contained ranges to be evaluated eagerly, you can do that in the Add method:
Add(range.ToList());
You can now use this class for any type which implements the addition operator:
var bunchOInt32s = new VTBunchOLists<int>();
bunchOInt32s.Add(10, 1, 15);
var bunchODoubles = new VTBunchOLists<double>();
bunchODoubles.Add(Math.PI, Math.E, 10, false);
public class Foo
{
public int Number { get; set; }
public static Foo operator+(Foo left, Foo right)
{
return new Foo { Number = left.Number + right.Number };
}
}
var bunchOFoos = new VTBunchOLists<Foo>();
bunchOFoos.Add(new Foo(), new Foo { Number = 5 }, 3);
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I am crafting a guitar tuner and I came across a problem. I am not sure how I can have the audio input be set to 440hz. Any suggestions?
|
|
|
|
|
Ask on a hardware site, rather than software?
What does this have to do with C#?
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Supposing you want use C# to write your program, it seems that you are a little bit confused: do you want pickup the A tone (La 440Hz) with microphone or you want your speakers play a sinusoidal 440Hz tone?
But anyway why don't you start using search engines? Googling you'll find many open source programs that do that.
One from FFT Guitar Tuner from Codeproject[^], or this from Sourgeforge[^]...
|
|
|
|
|
|
Currently we're using in code <System.Web.Services.WebService(Namespace:="https://ourservice/")> to set the namespace, can this be done in web.config, instead? I've looked but can't find where?
VS2008, ASMX web service.
|
|
|
|
|
|
|
When I add an item to the datagridview (from another form), it shows up just fine. But when I try to add another item to the datagridview, only the new item appears, and the previous one gets thrown out, it appears.
Note that I'm using .Hide, and .Show, to move between two forms (add_form and main_form). I've tried using .ShowDialog to see if it would fix the problem, but instead I get multiple instances of the same window open after moving back and forth between forms.
How can I fix this problem?
Here is the code that adds to the DGV:
private void add_Click(object sender, EventArgs e)
{
invmain invmainobject = new invmain();
switch(combobox1.SelectedIndex)
{
case 0:
invmainobject.datagridview1.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 1:
invmainobject.datagridview2.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 2:
invmainobject.datagridview3.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 3:
invmainobject.datagridview4.Rows.Add(itembox.Text, quantitybox.Text);
break;
default:
MessageBox.Show("Please select a category.\t\t");
combobox1.Focus();
return;
}
invmainobject.Show();
this.Close();
|
|
|
|
|
I suspect your problem has nothing to do with adding items to the datagrid, but everything to do with how you're handling the forms that contain/manipulate the grid:
Quote: but instead I get multiple instances of the same window open after moving back and forth between forms.
You have to show the code that is creating/showing these forms as you are probably creating new instances of the forms instead of managing the existing forms properly.
|
|
|
|
|
Here is the code for the main page where the tab control is, with the four DGV's:
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 WindowsFormsApplication1
{
public partial class invmain : Form
{
public invmain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
cover form1 = new cover();
form1.Show();
this.Hide();
}
private void button2_Click(object sender, EventArgs e)
{
additem form1 = new additem();
form1.Show();
this.Hide();
}
private void deletebutton_Click(object sender, EventArgs e)
{
DialogResult deleteitem = MessageBox.Show("Delete selected item?\t\t\t", "Delete Item", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (deleteitem == DialogResult.Yes)
{
foreach (DataGridViewRow item in this.datagridview1.Rows)
{
datagridview1.Rows.RemoveAt(item.Index);
}
foreach (DataGridViewRow item in this.datagridview2.Rows)
{
datagridview2.Rows.RemoveAt(item.Index);
}
foreach (DataGridViewRow item in this.datagridview3.Rows)
{
datagridview3.Rows.RemoveAt(item.Index);
}
foreach (DataGridViewRow item in this.datagridview4.Rows)
{
datagridview4.Rows.RemoveAt(item.Index);
}
MessageBox.Show("Item deleted.\t\t\t", "Delete Item", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
And here is the additem page, where after clicking add, the item and quantity should be added to the appropriate DGV after selecting a valid category:
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 WindowsFormsApplication1
{
public partial class additem : Form
{
public additem()
{
InitializeComponent();
datetimelabel.Text = DateTime.Now.ToString("MM/dd/yyyy");
this.quantitybox.KeyPress += new KeyPressEventHandler(quantitybox_KeyPress);
}
private void additem_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
invmain form1 = new invmain();
form1.Show();
this.Hide();
}
private void quantitybox_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !(char.IsDigit(e.KeyChar) || e.KeyChar == '\b');
}
private void add_Click(object sender, EventArgs e)
{
invmain invmainobject = new invmain();
switch(combobox1.SelectedIndex)
{
case 0:
invmainobject.datagridview1.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 1:
invmainobject.datagridview2.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 2:
invmainobject.datagridview3.Rows.Add(itembox.Text, quantitybox.Text);
break;
case 3:
invmainobject.datagridview4.Rows.Add(itembox.Text, quantitybox.Text);
break;
default:
MessageBox.Show("Please select a category.\t\t", "Required Field Missing", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
combobox1.Focus();
return;
}
if (string.IsNullOrWhiteSpace(this.itembox.Text))
{
MessageBox.Show("The 'Item' field is required.\t\t\t", "Required Field Missing", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
itembox.Focus();
return;
}
if (string.IsNullOrWhiteSpace(this.quantitybox.Text))
{
MessageBox.Show("The 'Quantity' field is required.\t\t\t", "Required Field Missing", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
quantitybox.Focus();
return;
}
invmainobject.Show();
this.Close();
}
private void button1_Click_1(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
if (open.ShowDialog() == DialogResult.OK)
uploadpic.Image = Bitmap.FromFile(open.FileName);
}
}
}
Note that I'm no longer using .ShowDialog(), because of the trouble of multiple forms I got.
modified 27-Feb-15 18:16pm.
|
|
|
|
|
OK, a few things. First, you haven't solved the problem of multiple forms. You've just hidden them and never reusing the them. You're creating a new instance of every form on every button click, even your MAIN FORM!!
You're using the default names for all of your controls. DON'T! I have no idea what "button1" does and, in a years time, neither will you. Always give your controls and variables meaningful names.
If these two button controls on your main form with the grids and just there to get data from the user to add to the grid, you should create an instance of the data entry form and show it with ShowDialog. When the user clicks OK on that form control will return to the line right after the ShowDialog call. You can then get the data from that form, put it in your grids, then Dispose the form.
Next, when you go and clear all the rows from your datagrids, you don't need loops to delete each row from the girds. Look at the documentation for the Rows collection. There's a Clear() method on it. Call that and you wipe out every row in your datagrid in a single line of code.
|
|
|
|
|
I don't understand what I should change so that it would keep adding to the DGV (or any DGV, based on the category selected), and not deleting previous entries...
NOTE: this is only my first week of programming
|
|
|
|
|
This is your first week of programming and you've got data grids and new forms and stuff? Yeah, WAY over your head. Talk about jumping into the deep end of the pool without knowing how to swim.
Dim entryForm As New EntryForm
Dim result As DialogResult = entryForm.ShowDialog()
If result = DialogResult.Ok Then
whatever = entryForm.WhateverTextBox.Text
End If
entryForm.Dispose()
You don't put any code on the data entry form to switch back to the original main form. NONE AT ALL.
|
|
|
|
|
No, not really. C# is a pretty straightforward language; it's just this small hiccup I've run into.
How do I make it switch back to the original form?
|
|
|
|
|
Nothing. You put a button on your form, give it any text you want, like "OK", and then set the forms AcceptButton property to that button.
Well, there is one line of code you have to put into the Click event handler for that button:
Me.DialogResult = DialogResult.OK
That's it.
|
|
|
|
|
Hi,
Is there a way to automate (is it exposed) Lync loading a meeting url, the way that Outlook does when you click the link inside of the meeting and it calls Lync and opens the meeting?
Lync 2013 and Outlook 2010 and C sharp.
I've been looking through the Lync SDK and I haven't found any examples of this. I have the Lync url from Exchange already, I only need to know how to pass it to Lync and get Lync to spawn a meeting with it.
Thanks
|
|
|
|
|
turbosupramk3 wrote: the way that Outlook does when you click the link inside of the meeting Outlook sends me a clickable link; right click on the link and select "copy hyperlink". Next, shellexecute the link.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks Eddy, I figured out that it actually tries to use IE first, so I was able to mimic the same behavior with the following code
if (lyncUrl != "")
{
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe", lyncUrl);
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process.Start(startInfo);
}
else
{
MessageBox.Show("Lync url is blank or non existant");
}
|
|
|
|
|