falls es sich hierbei um eine App handelt, deren Quellcode du hast, könntest du per IPC über ein eigens definiertes Interface die App ansprechen.
Ansonsten bist du, so wie ich das sehe, schon mal auf dem richtigen Weg. Bezühlich Spy++ kann ich dir leider nichts über das Herausfinden der Handles sagen.
ich habe nach langer Zeit endlich wieder was, worauf ich im Netz nichts finden konnte.
Ich habe ein Objekt mit dem BinaryFormatter serialisiert.
Nun möchte ich dieses Objekt in ein anderes Objekt deserialisieren (migrieren).
Das ist mit dem SerializationBinder schonmal kein Problem, wenn die Properties der Objekte übereinstimmen.
Wenn die Properties jedoch abweichen, wird da ISerializable auf dem neuen Objekt nötig, um die Properties entsprechend zu übernehmen.
Jetzt zum Problem: Wenn ich ISerializable implementiere, kommt am Ende eine Null-Referenz anstelle des neuen Objekts raus. Wenn ich das Interface weglasse, funktioniert alles - bis auf die Properties, die nicht gefüllt sind, weil sie sich im Namen vom alten Objekt unterscheiden.
Deserialisung
public Car Deserialize(Stream stream)
{
stream.Position = 0;
var f = new BinaryFormatter();
f.Binder = new VehicleToCarBinder();
return (Car)f.Deserialize(stream);
}
VehicleToCarBinder
public class VehicleToCarBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName == typeof(Vehicle).FullName)
return typeof(Car);
if (typeName == typeof(List<Namespace1.Wheel>).FullName)
return typeof(List<Namespace2.Wheel>);
if (typeName == typeof(Namespace1.Wheel).FullName)
return typeof(Namespace2.Wheel);
return null;
}
}
Betroffenes (neues) Objekt
namespace Namespace2
{
[Serializable]
public class Wheel// : ISerializable // <-- Interface auskommentieren: Unit-Test funktioniert (logischerweise ohne Property-Werte)
{
public Wheel()
{
}
protected Wheel(SerializationInfo info, StreamingContext context)
{
Inches = (int)info.GetValue("<Size>k__BackingField", typeof(int));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("<Size>k__BackingField", Inches);
}
public int Inches { get; set; }
public string Type { get; set; }
}
}
Der Test
[TestMethod]
public void SerializeVehicle()
{
var vehicle = new Vehicle();
vehicle.Wheels.Add(new Wheel { Size = 15, Type = "Soft" });
vehicle.Wheels.Add(new Wheel { Size = 15, Type = "Hard" });
var serializer = new VehicleSerializer();
var stream = serializer.Serialize(vehicle);
var car = serializer.Deserialize(stream);
Assert.IsNotNull(car.Wheels[0]);
Assert.IsNotNull(car.Wheels[1]);
Assert.AreEqual(vehicle.Wheels[0].Type, car.Wheels[0].Type);
// Die letzten beiden Tests sollten am Ende auch funktionieren
//Assert.AreEqual(vehicle.Wheels[0].Size, car.Wheels[0].Inches);
//Assert.AreEqual(vehicle.Wheels[1].Size, car.Wheels[1].Inches);
}
Anbei ist das Ganze als lauffähige Solution angehängt.
Ich hoffe, jemand stand schonmal vor dieser Problematik.
Zum Speicherverbrauch:
Bei vielen Einträgen stößt man halt mit der ListView an ihre Grenzen. Entweder würde ich die ListView pagen oder es mit dem DataGridView probieren, sollte grundsätzlich Speicherschonender sein.
Vermutlich steht der SelectionMode nicht auf Cell (oder so ähnlich)?
Weiß jetzt gerade nicht die korrekten Properties, aber in die Richtung könnte es gehen.
Ich hätte dazu eine Idee, die Umsetzung der Bitte zu pushen.
Man sollte die Hilfesuchenden doch auch einfach mal fragen (nicht rügen), was aus ihrem Problem geworden ist und warum die (evtl.) Treffer nicht gepostet wurden.
Es könnte nämlich auch gut sein, dass man in der Zwischenzeit das Problem anderweitig gelöst hat (von selbst, Google).
Die Idee, das Ganze zu pushen, liegt darin, geöffnete Threads als [ungelöst] zu markieren. Und der User diese als [gelöst] markieren kann, sobald er eine Lösung hat. Natürlich unter der sinnvollen Voraussetzung, dass er ebenso die Lösung postet.
Was ich auch nicht schlecht finde, ist die Markierung eines Posts als "most helpful/best answer" und z.B. direkt unter dem Eingangspost gepinned ist.
Ich denke einfach nur, dass das den Hilfesuchenden mehr motiviert, den Thread qualitativ und im Sinne der Community zu gestalten. Ich empfinde es als "unangenehm" wenn der Thread mit ner dicken roten Schrift vorangestellt ist, und wenn ich doch eine Lösung für mein Problem habe, dann lasse ich die rote Schrift verschwinden und bin zufrieden.
Was dort etwas "krass" ist - wie ich finde, aber vielleicht akzeptabel - dass man als Threadersteller eine PN bekommt, sobald eine Antwort verfasst wurde und man prüfen soll, ob das die Lösung war, um dann den Thread als gelöst und die beste Antwort zu markieren.
Bei Windows-Controls ist das etwas schwerer mit dem Zeichnen.
Du könntest viel eher versuchen, WM_PAINT (Stichwort: P/Invoke) zu behandeln und dort deine Zeichenroutine versuchen.
Aber das ist alles wieder so experimentell, erst recht deine Idee, die Methode technisch zu Überschreiben.
Selbst wenn du sie überschreiben würdest, meines Wissens nach ist das Zeichnen zu dem Zeitpunkt bereits geschehen.
Die einzig wirkungsvolle Variante, einen System.Windows.Forms.Button vom Zeichnen abzuhalten, sehe ich nur in einem eigenen IMessageFilter, der WM_PAINT für Buttons dann einfach nicht behandelt. In etwa so:
Zur Design-Zeit, ja.
Es geht ja gerade darum, dass du per Paint-Event den System.Windows.Forms.Button nicht groß beeinflussen kannst. Und ich meine, dass das mit ButtonBase zu bewerkstelligen sein müsste.
Danke für die Info!
Kommt gerade recht. Sind schon am Planen, das TE Edit Control durch TXText Control zu ersetzen. Mal schauen, ob dafür die Express-Version ausreicht.
Kurz und primitiv zusammengefasst: Wenn du mit Threads arbeitest und aus einem Thread heraus an deiner grafischen Oberfläche etwas anzeigen willst, musst du mit Invoke arbeiten, da sich das GUI in einem anderen Thread befindet.
so ganz verstehe ich dein Problem jetzt nicht. Wenn du eine Klasse hast, die sich um das UDP Handling kümmert, ist es dir egal, ob die Start-Methode synchron oder asynchron ausgeführt wird.
class UDP
{
public void Start(int port)
{
ThreadPool.QueueUserWorkItem(StartInternal, port);
}
private void StartInternal(object _port)
{
int port = (int)_port;
// ...
if (DeinEvent != null)
{
DeinEvent(this, EventArgs.Empty);
}
}
public event EventHandler DeinEvent;
}
Die Methode heißt doch set_DefaultFilePath! Und ob da BindingFlags.SetProperty funktioniert, weiß ich nicht. Es ist immerhin eine Methode, die aufgerufen wird, und nicht ein Property.
IMHO:
Das liegt auch daran, dass "Windows" mittlerweile viel mehr ein eigenständiger Name ist, mit dem man einfach nur das Betriebssystem in Verbindung bringt, ohne dabei an die Fenster zu denken.
Daher denke ich, wird Windows als Name auch bleiben, sonst wäre ja der gewichtige Marktname zerstört. Außerdem soll ja Windows an sich im Unterbau erhalten bleiben :-) Und wenn ich das richtig aufgefasst habe, sind die Tiles nur ein Aufsatz, gedacht als primäre Oberfläche.
Windows Tiles könnte ich mir von daher vielleicht als Name vorstellen.
Du kannst doch die Bilder statisch in deiner Anwendung buffern. Da du ja die URL zu dem Bild hast, reicht doch ein simples <string, Image>Dictionary völlig aus, oder habe ich jetzt etwas übersehen?
Kann mich nicht genau vorstellen, was du genau machst? Sind das Vorschaubilder deiner Suchergebnisse, sind die Bilder immer gleich? Wieso werden diese immer neu geladen?
Ich habe jetzt den Grund für meine Verwirrung gefunden.
Ich habe AddValueChanged in einigen Projekten benutzt, um ein Objekt zu überwachen, über das ich selbst nicht die Kontrolle habe. Und anscheinend werden die Properties auf dem Objekt mit SetValue gesetzt. Das war mir nicht bewusst.
Du musst in den Setter den entsprechenden Code schreiben - sollte aber genügend Beispiele dazu geben.
Das Event will ich ja auch gar nicht selber auslösen. Das soll ja eben automatisch über den PropertyDescriptor mit AddValueChanged geschehen.
Verstehe ich eure Hinweise also richtig, für jedes Property ein -Changed Event bereitzustellen? Wo ist denn da noch der Mehrwert von AddValueChanged?
Ich bin mir auch mittlerweile nicht mehr sicher, ob wir noch von dem selben Problem sprechen..
Ich hab das bisher immer so gemacht, den PropertyDescriptor jedes Property's einer Klasse zu durchlaufen und in AddValueChanged eine stupide Methode zu hinterlegen, die aufgerufen wird, sobald sich irgendein Property-Wert ändert, was aber nicht passiert.
bezüglich VS Express: Hat damit absolut gar nichts zu tun, da das ja nen Thema der Runtime und nicht der IDE ist.
Ich weiß :) Das sind aber diese Momente wo ich anfange, alles in Erwägung zu ziehen :)
Das mit dem Interface habe ich schon drin gehabt, hab das im Post nur ausgelassen.
Habe jetzt nochmal ein neues Sample gemacht. Sowohl Interface implementiert, als auch EventHandler ValueChanged zusätzlich bereitgestellt:
class Program
{
static void Main(string[] args)
{
var i = new MyClass();
i.ValueChanged += new EventHandler(i_ValueChanged);
i.PropertyChanged += new PropertyChangedEventHandler(i_PropertyChanged);
i.Property = "test";
Console.ReadLine();
}
static void i_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("Property value changed");
}
static void i_ValueChanged(object sender, EventArgs e)
{
Console.WriteLine("Property value changed");
}
}
public class MyClass : INotifyPropertyChanged
{
public MyClass()
{
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(this))
{
pd.AddValueChanged(this, this.OnValueChanged);
}
}
private void OnValueChanged(object sender, EventArgs e)
{
if (this.ValueChanged != null)
{
this.ValueChanged(this, new PropertyChangedEventArgs(""));
}
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(""));
}
}
public event EventHandler ValueChanged;
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
#endregion
public string Property { get; set; }
}
An sich nichts spektakuläres. Der übergebene Handler in AddValueChanged wird nie aufgerufen, wenn sich ein Property-Wert ändert. Vielleicht seh ich gerade auch den Wald vor lauter Bäumen nicht. Aber ich kann keinen Fehler entdecken.
Hier die vollständige Test-Klasse, mit der es (bei mir) nicht funktioniert:
public class Class1
{
public void Test()
{
this.Value = 0;
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(this))
{
pd.AddValueChanged(this, this.OnPropertyValueChanged);
}
// Wertänderungsbenachrichtigung erzwingen
this.Value = 4711;
this.Value = 0815;
}
private void OnPropertyValueChanged(object sender, EventArgs e)
{
// Wird nie aufgerufen
Debug.Assert(false, "this.Value changed: " + this.Value);
}
public int Value { get; set; }
}
var test = new Class1();
test.Test();
Im Internet finde ich keine nützliche Informationen. Und da es so schon immer funktioniert hat, wollte ich auch nicht auf das "neue" DependencyProperty Handling umsteigen.
Das einzige was ich gefunden habe, ist das SupportChangeEvents Property auf dem PropertyDescriptor was auf false steht, was mit der Nicht-Benachrichtigung zu tun haben könnte. Aber damit kann ich auch nicht viel anfangen, da ich auch Basistypen wie int und string verwende. Ich musste mich auch nie darum kümmern.
Das Ganze habe ich in einer VM (Windows XP SP 3) mit Visual C# Express 2010 am Laufen. Ich kann mir nicht vorstellen, dass die Express Version solche Einschränkungen hat?!
Was heißt genau "sobald du DoubleBuffering verwendest"?
Edit: Hab das mal versucht, nachzustellen. Scheint so nix zu helfen. Da Transparenz, vor allem in GDI/+ sehr langsam ist, ist wohl WPF die bessere Wahl, wenn du damit rumspielen willst.
public class MagicPanel : Control
{
public MagicPanel()
{
this.SetStyle(
ControlStyles.SupportsTransparentBackColor | /* wichtig */
ControlStyles.UserPaint | /* benötigt */
ControlStyles.AllPaintingInWmPaint | /* benötigt */
ControlStyles.OptimizedDoubleBuffer | /* Mit oder ohne, gleiches Verhalten */
ControlStyles.ContainerControl | /* optional */
ControlStyles.ResizeRedraw, /* optional */
true);
}
}
Zu 1) Das Thema hatte mich mal auch interessiert und bin bisher nicht wirklich zu einer eindeutigen bzw. schlüssigen Antwort gekommen. Viele sagen, dass es sogar keinen Unterschied machst, ob du die Column 'Is Unique' machst oder als Type 'Index' oder 'Unique' auswählst. Der Index kommt letztendlich immer drauf. Aber dem traue ich nicht so ganz. Lässt sich aber eigentlich leicht feststellen, ob das so ist (Index-Einträge ansehen). Bin nur grad nicht in der Lage dies zu tun.