|
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Gerry Schmitz wrote: Your design is flawed;
Good catch.
That would need to be resolved before anything can proceed.
|
|
|
|
|
I have an ItemObservableCollection called _MyChildren with a collection of clsChild. I am trying to get nonfictions when a clsChild.name string is changed.
Error I am getting on MyChildren.ItemPropertyChanged:
Severity Code Description Project File Line Suppression State
Error CS1661 Cannot convert anonymous method to type 'EventHandler<ItemPropertyChangedEventArgs<clsChild>>' because the parameter types do not match the delegate parameter types C-Sharp-Tests C:\Users\Jeff\Documents\GitHub\C-Sharp-Tests\C-Sharp-Tests\C-Sharp-Tests\clsParent.cs 21 Active
clsParent:
using Countdown;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C_Sharp_Tests
{
internal class clsParent : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ItemObservableCollection<clsChild> _MyChildren;
public clsParent()
{
_MyChildren = new ItemObservableCollection<clsChild>();
this._MyChildren.ItemPropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (string.Equals("IsChanged", e.PropertyName, StringComparison.Ordinal))
{
this.RaisePropertyChanged("IsChanged");
}
};
}
}
}
clsChild:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C_Sharp_Tests
{
internal class clsChild : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string name { get; set; }
}
}
ItemObservableCollection:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Countdown
{
public sealed class ItemObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public event EventHandler<ItemPropertyChangedEventArgs<T>> ItemPropertyChanged;
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
item.PropertyChanged += item_PropertyChanged;
}
protected override void RemoveItem(int index)
{
var item = this[index];
base.RemoveItem(index);
item.PropertyChanged -= item_PropertyChanged;
}
protected override void ClearItems()
{
foreach (var item in this)
{
item.PropertyChanged -= item_PropertyChanged;
}
base.ClearItems();
}
protected override void SetItem(int index, T item)
{
var oldItem = this[index];
oldItem.PropertyChanged -= item_PropertyChanged;
base.SetItem(index, item);
item.PropertyChanged += item_PropertyChanged;
}
private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnItemPropertyChanged((T)sender, e.PropertyName);
}
private void OnItemPropertyChanged(T item, string propertyName)
{
var handler = this.ItemPropertyChanged;
if (handler != null)
{
handler(this, new ItemPropertyChangedEventArgs<T>(item, propertyName));
}
}
}
public sealed class ItemPropertyChangedEventArgs<T> : EventArgs
{
private readonly T _item;
private readonly string _propertyName;
public ItemPropertyChangedEventArgs(T item, string propertyName)
{
_item = item;
_propertyName = propertyName;
}
public T Item
{
get { return _item; }
}
public string PropertyName
{
get { return _propertyName; }
}
}
}
|
|
|
|
|
I don't see why you just didn't stick with ObservableCollection. It's concurrent for read only. You simply "subscribe / unsubscribe". As if you can predict what properties to refresh on the client side.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I've known about Visual Studio user secrets for a while but haven't used them. And I know that GitHub has secrets, which can be used in repos and I'm sure GH Actions, but again I haven't used them.
That's all going to change very soon. I'd like to use VS user secrets for connection strings, API keys, etc. But when I commit to a GH repo, I'd like the GH action to use the GH secrets saved in that repo on GH. The only thing is, how do I do that? The syntax, I'm sure, isn't the same. How do I do what I want to do?
Rod
|
|
|
|
|
|
Thank you, Richard. I'm reading the document you linked to now. I'm about a third of the way through it. It speaks of ASP.NET Core, which in my case is fine, as this is a new app. However, we have hundreds of custom apps all written using old versions of the .NET Framework. Does that mean that Visual Studio user secrets will not work?
Rod
|
|
|
|
|
Rod at work wrote: Does that mean that Visual Studio user secrets will not work? Sorry, I do not know the defoinitive answer, but there is a section on that page titled "Migrating User Secrets from ASP.NET Framework to ASP.NET Core", which may help.
|
|
|
|
|
I've finished reading the document and I did see that "*Migrating User Secrets from ASP.NET Framework to ASP.NET Core*". Unfortunately, that won't work for me. I wish we were allowed to update code, but the motto where I work is, "If the code isn't broken beyond repair, do NOT modify it!! And NEVER, EVER update or upgrade it!!!" I have no choice but to work on old code using whatever .NET Framework it was originally written in. And some of those dates back to .NET Framework 1.1.
Rod
|
|
|
|
|
Another issue I'm unclear on, in reference to that "Safe storage" document, is the use of environmental variables for safely storing secrets. The document brings up environmental variables, saying that is a safe way to use secrets securely, then drops talking about environmental variables. Please excuse my abysmal ignorance on how to use environmental variables on a development machine, on the deployed server and an Azure App Service. How does that work?
Rod
|
|
|
|
|
Sorry, I have not studied the paper in detail. I think you may need to ask Microsoft for clarification.
|
|
|
|
|
Rod at work wrote: The only thing is, how do I do that
By providing a key that only shows up on a developer machine. Such as a specific single env variable. It only exists on dev machines. The code uses different code based on whether that exists or not.
The env variable does not provide security information itself. It just exists.
That allows for no security problems because if it starts existing on a prod box nothing will work.
This solves your github problem.
Rod at work wrote: However, we have hundreds of custom apps...And NEVER, EVER update or upgrade it!!!
(From other posts)
Which is exactly correct. If you bring an app forward then that tech debt activity should make NO functional changes except those necessary to bring it forward. These days one can often make that case to do that for existing code both for obsolesce and security reasons.
But besides that presumably those apps are already managing secret information via some mechanism and you should not attempt to use another idiom unless there is a real need. It does not add value to have multiple idioms that one must know to provide maintenance and just to do development.
|
|
|
|
|
I'm going to consider what you've said here concerning environmental variables. You've given me some things to think about.
I did want to respond to your suggestion of not changing the idiom for how we handle secrets to another idiom. In this case I believe we will have to when migrating to repos in GitHub. As I understand GH Advanced Security, it will run a check on attempted commits to see if secrets are in the proposed commit. If secrets are there, then the commit/push will be rejected. Secrets are in all our source code. (If I've misunderstood how GH Advanced Security works, with respect to secrets, then please forgive and correct me.)
Rod
|
|
|
|
|
Rod at work wrote: Secrets are in all our source code.
Well that is a problem!
Perhaps you should find a solution for the older apps first. Updating only that part.
Only then, and to be a consistent, new apps would use it in the same way.
Not to give away a secret though - I doubt github can find all secrets. So you can probably find a way to obfuscate in the code. But that should be a stopgap.
|
|
|
|
|
Hi!
I'm a beginner in C# and need some help.
In Winforms I've got a button. When I press the button I'd like to get some data from TMDB and insert it to MS SQL.
I've redacted some properties to cut down unnecessary properties.
This is what I've got:
Forms.cs:
public void btn_GetNewTVShowData_Click(object sender, EventArgs e)
{
GetTMDB GetData = new GetTMDB();
GetData.GetTvShowData();
}
DataClasses\Common\GetTMDB.cs
DataClasses\Common\GetTMDB.cs
namespace WinFormsApp1.DataClasses.Common
{
internal class GetTMDB
{
public async Task<string> GetTvShowData()
{
HttpClient client = new HttpClient();
var content = await client.GetStringAsync("https://api.themoviedb.org/3/tv/136311?api_key=XXXXXXX&language=en-US");
TVShow myDeserializedClass = JsonConvert.DeserializeObject<TVShow>(content);
return object myDeserializedClass; <-- Not working, I know
}
public class TVShow
{
public string backdrop_path { get; set; } = default!;
public List<CreatedBy> created_by { get; set; } = default!;
public string name { get; set; } = default!;
}
public class CreatedBy
{
public int id { get; set; } = default!;
public string credit_id { get; set; } = default!;
public string name { get; set; } = default!;
public int gender { get; set; } = default!;
public string profile_path { get; set; } = default!;
}
}
}
DataClasses\Common\DataAccess.cs (psedocode, just for showing I want it in seperate class)
INSERT INTO table_name (column1, column2) VALUES (value1, value2);
So, I want to press a button, use the class GetTMDB, get the json from TMDB, Serialize it (with NewtonSoft.json), return the data back to my forms1.cs (I guess? Or should I call DataAccess.cs?).
Is it possible to let another class access the properties?
Let's say I want multiple classes to access the Properties to do different kind of stuff with my properties.
|
|
|
|
|
You have way too many things going on (for a "beginner"), and that are wrong. You need to pick some aspect and ask for help on that instead of asking for what amounts to a course in C# programming and systems design.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
First, you're return type is a Task<string>, not what you're really returning, so you have to fix that.
Next, the return statement just needs the "object" part removed.
Lastly, the other answer is correct. You're jumping in the deep end without knowing how to swim.
This is NOT tested, so don't go expecting this to work immediately:
public async TVShow GetTvShowData()
{
HttpClient client = new HttpClient();
var content = await client.GetStringAsync("https://api.themoviedb.org/3/tv/136311?api_key=XXXXXXX&language=en-US");
TVShow myDeserializedClass = JsonConvert.DeserializeObject<TVShow>(content);
return myDeserializedClass;
}
|
|
|
|
|
I'm a bit confused on something.
I have a Sharepoint class with a DownloadFileAsync method:
using System.IO;
using System.Threading.Tasks;
namespace WpfApp1
{
internal class Sharepoint
{
public async Task DownloadFileAsync(string folderName, string downloadPath = null)
{
var url = _clientContext.Web.ServerRelativeUrl + "/Shared%20Documents/" + folderName;
Folder targetFolder = _clientContext.Web.GetFolderByServerRelativeUrl(url);
_clientContext.Load(targetFolder.Files);
await _clientContext.ExecuteQueryAsync();
foreach (var file in targetFolder.Files)
{
FileInformation sharepointFile = Microsoft.SharePoint.Client.File.OpenBinaryDirect(_clientContext, file.ServerRelativeUrl);
await _clientContext.ExecuteQueryAsync();
var path = string.IsNullOrEmpty(downloadPath) ? DEFAULT_DIRECTORY : downloadPath;
path = path + @"\" + file.Name;
using (FileStream filestream = new FileStream(path, FileMode.Create))
{
sharepointFile.Stream.CopyTo(filestream);
}
}
}
}
}
It is called from a Repository class
using System.IO;
using System.Threading.Tasks;
namespace WpfApp1
{
internal class Repository
{
string _appPath;
Sharepoint _sharePoint;
public Repository()
{
_sharePoint = new Sharepoint();
_appPath = $"{Path.GetTempPath()}RDSPaymentProcessing";
}
public async Task<MyData> GETDataAsync()
{
var results = new MyData();
var fileName = $"{Path.GetTempPath()}{LOCAL_APP_DATA_FOLDER}\sharepointdata.xml";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
await _sharePoint.DownloadFile(SETINGS_FOLDER, _appPath);
if (File.Exists(fileName))
{
results = Serialization.DeSerializeObject<MyData>(fileName);
}
else
{
throw new FileNotFoundException(fileName);
}
return results;
}
}
}
and that is called from the MainWindowViewModel's loaded method:
namespace WpfApp1
{
internal class MainWindowViewModel
{
private MyEntity _data;
public async void WindowLoadedExecuted()
{
await _repository.GETDataAsync();
}
}
}
The question is about where to use await/async? I want to UI to be responsive throughout all of this? Am I coding this right? Or does await/async only need to be on the Sharepoint class?
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|
Use a BackgroundWorker; it's easier to get one's head around. About the only thing one is interested in with async is:
1) Is it finished (callback)
2) When can I use the data (use "concurrent" collections and events).
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Hmm. I always thought background workers were 'outdated'. Seems to me that all you hear about these days is async/await.
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|
Wood working tools are also "outdated" by that logic.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
You should generally avoid async void methods[^]. As per David Fowler's async guidance[^], you can either use Task.Run to push the execution onto a background thread, or call a Task -returning method and "discard" the returned task. Either option will allow exceptions to fire the TaskScheduler.UnobservedTaskException event[^] rather than crashing the application from the finalizer thread.
In this case:
internal class MainWindowViewModel
{
private MyEntity _data;
private async Task LoadData()
{
_data = await _repository.GETDataAsync();
}
public void WindowLoadedExecuted()
{
_ = LoadData();
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Okay, I don't think this is a rant, but there may be some ranting. I've been a developer for a very very long time (I won't say how long, but let's just say I used to use Borland OWL). I understand that languages and libraries progress, morph, and change over time. That is natural.
However, being someone that came from the days where you can drag a button onto a window, double click it and add the code (Forms), and when you want to modify it, you just do it in the editor, to this last application I am making using WinUI 3, which I find painful to make.
Is it just me, or have we taken a massive step backwards? Not having a GUI editor for making GUIs, and then having to download an application (WinUI 3 Examples) that shows how components and code need added, is just stupid to me. Not to mention that when you use panels, stack panels, grids and all that in XML, and then you realize you have to introduce another set of controls into an existing GUI....and see that it takes like hours of rework to get it not to be a mess again...WTF? Why are we moving in this direction? Not to mention, WinUI 3 seems wonky and lacking in performance relative the predecessors.
So, my general question is... Why does WinUI 3 bring to the table that is so good that you would abandon the ability to have a GUI editor, and hand jam everything in. This is no better than the first days of windows when we all had to make GUIs by editing the resource files.
So again. Why is Windows Forms falling out of favor, Why is WPF even being replaced by something that seems more obtuse?
I am going to build another App soon, and I would like someone to tell me why Windows Forms is not a good choice over WinUI 3.... Anyone?
Thanks.
|
|
|
|
|
I develop in WPF and (mainly) UWP. I have developed in Windows Forms. WinUI2 and WinUI3 look very similar to me. I use WinUI2 in UWP via a "using" to get some extra features that don't stand out in my mind at the moment. To use WinUI3, I have to do something I can't be bothered with for now.
I use the Visual Studio "GUI editor" in any case; prefering to work in XAML directly.
XAML (and UWP) is more "fun" for me than the alternatives. My app also "fits" on "mobile", tablet, PC, XBox and can run on ARM. My second choice would be WPF.
But you can do a lot with (any) .EXE these days.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I started programming before OWL existed (my first IDE was Turbo Pascal for CP/M on an Apple //e back in the early 80's).
I went through Pascal (OWL), C++ (MFC), and then C# (WinForms, and currently WPF). I refuse to code for WinUI, simply because I have no desire to learn it.
It took me a while to accept WPF (and I fought it HARD), but I find it easy to do (easier than WinForms in a lot of ways). I do all of my design work in the XAML editor (you can drag from the Toolbox pane to the XAML to get a new control on the page, and intellisense guides you when you start changing properties in the XAML, so it's not TOO bad).
After two years away from desktop apps, I spent the last weekend doing a WPF version (proof of concept) of our web app from work, and the hardest part was making the app allow the user to adjust font size with Ctrl+ and Ctrl- like a web browser (we have to comply with Section 508 by allowing the font in an application to be increased by up to 200%). A few years ago, I wrote a custom message box library that allows the developer to specify text size and custom colors (among other features), and with a little tweaking, my message boxes use the increased font size.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|