Laden...

Forenbeiträge von sharpType Ingesamt 228 Beiträge

04.08.2014 - 11:25 Uhr

Hallo zurück,

es gibt keine zweite XML, von daher lädt er die Richtige X(

Das Problem ist, dass es scheinbar nur auf meinem Rechner nicht funktioniert. Ich bekomme nach wie vor die Fehlermeldung und ich weiß einfach nicht, wodran es liegen könnte 🙁

28.07.2014 - 16:46 Uhr

Hallo Profis,

meine letzte Anlaufstelle seid ihr, nachdem ich jetzt schon am verzeifeln bin und das halbe Netz abgesucht habe 🙁

Folgendes Problem: Ich möchte ein Outlook Add-in programmieren, welches ein zusätzliches Ribbon direkt in die Terminansicht einfügt und das am besten ganz vorne in die Ribbon-Leiste. Ich möchte also die vorhandene Ribbon-Leiste erweitern.

Wenn ich das Outlook Add-in in VS 2010 Pro erstelle und die XML-Datei einfüge und sie wie folgt manipuliere:


<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
  <ribbon>
    <tabs>
      <tab idMso="TabAppointment">
        <group id="MyGroup"
               label="My Group">
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

bekomme ich den Fehler "Das Office-Steuerelement wurde anhand der ID nicht gefunden." (s. Anhang).

Auch diese Lösung:


<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon>
    <contextualTabs>
      <tabSet idMso="TabSetAppointment">
        <tab idMso="TabAppointment">
          <group id="group1" label="Normal Meeting Group" />
        </tab>
      </tabSet>
      <tabSet idMso="TabSetReccurringAppointment">
        <tab idMso="TabRecurringAppointment">
          <group id="group2" label="Recurring Meeting Group" />
        </tab>
      </tabSet>
    </contextualTabs>
  </ribbon>
</customUI>

von

Outlook 2010 AddIn in the TabAppointment Tab

was eigentlich genau das beschreibt, was ich eigentlich möchte, erzeugt den obigen Fehler.

Nehme ich z. B. als idMso "TabCalendar", dann funktioniert es technisch wie gewünscht, aber die Group taucht natürlich in der Kalenderansicht auf und nicht im Termin. Irgendwas scheint mit meinem "TabAppointment" bzw. auch dem "TabSetAppointment" nicht zu stimmen, denn beides findet er nicht und ich weiß nicht warum 🙁

Hat jmd. vielleicht einen Tipp oder kann mir helfen?

Vielen vielen Dank.

Beste Grüße
Marc

30.01.2013 - 13:52 Uhr

So, nochmal der Vollständigkeit halber und danke nochmal an Sparkle für den Denkanstoß:

Ich habe in XAML nun folgendes definiert als "Darstellungsteil":


<ItemsControl x:Name="Collection" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyPoint}">
            <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <Ellipse Width="10" Height="10" Fill="Black" Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}"/>
            </Canvas>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>


ObservableCollection<MyPoint> points = new ObservableCollection<MyPoint>();

points.Add(new MyPoint(2, 100));
points.Add(new MyPoint(50, 20));
points.Add(new MyPoint(200, 200));
points.Add(new MyPoint(300, 370));

Collection.ItemsSource = points;

MyPoint ist bei mir ein Interface-Typ, um jedes Objekt aufzunehmen, welches das Interface implementiert. Das Interface "IDrawable2D" hat dann eine vorgeschriebene Property vom Typ "VisualizationData2D", welches eine Beschreibung enthält wie sich jedes einzelne Objekt darzustellen hat. Das ganze berechnet dann der Backgroundworker (und das kann er auch, da er nicht mit GUI-Elementen arbeitet). Der Worker fügt dann nach und nach seine Objekte - welche sich darstellen sollen - in die ObservableCollection hinzu (per Invoke) und die GUI zeichnet das entsprechende Element (als Template in XAML definiert) mit seinen Parametern aus der Klasse VisualizationData2D.

Perfekt 🙂

(MyPoint, die Darstellung als Ellipse sowie die obige Struktur sind Beispiele aus dem Internet, aber praktisch 1:1 abwandelbar)

Grüße

29.01.2013 - 15:53 Uhr

Ich kenne die Grundlagen, nicht falsch verstehen. Habe das nur leicht Missverstanden. Das grundsätzliche Vorgehen hat sich noch aus Forms-Zeiten so durchgeschliffen, manchmal braucht man einfach nen anderen Denkanstoß.

Ich denke ich werde das so machen, allerdings kein MVVM 😜 Also danke für den Tipp. 🙂

Es sieht sicher auch nicht verkehrt aus, wenn man sieht wie das Binding langsam die Elemente aufbaut, während der Worker die Observable-Collection füllt.

29.01.2013 - 15:44 Uhr

Andere Frage, ob ich es richtig verstanden habe @Binding/XAML:

Ich müsste in XAML z. B. eine Observable-Collection erstellen, die als Item-Templates z. B. Rectangles hat, welche ihre Eigenschaften übers Binding von meinen Datenklassen bekommt? 🤔

29.01.2013 - 15:31 Uhr

Natürlich sagen mir die Begriffe etwas. Es ist nur so, dass die Grafik aufbauend auf Datenklassen und deren spezifischen Inhalt individuell erstellt werden muss. Ich schaue mir gerade das Helix-Toolkit an, welches in dem einen Link zu finden war. Das sieht ziemlich brauchbar aus 🙂

@inflames: Jah der Worker kann arbeiten und hinterher kann ich alles zuweisen, der User wartet dann solange, wenns länger dauert. Es muss also nicht "on the fly" passieren.

29.01.2013 - 14:02 Uhr

Hallo zurück,

@inflames: Wieso ist der Beitrag durchgestrichen? Die Idee finde ich nicht schlecht, habs aber noch nicht probiert.

@sparkle: So ganz werde ich nicht schlau aus den Beiträgen, also inwiefern das hilfreich ist und zu dem Problem passt 🤔

Also nehmen wir mal an (äußerst vereinfacht), ich habe Folgendes:


private void Draw(Canvas tempCanvas)
        {
                // Define variables.
                Rectangle rect;

                     // Create rectangle.
                    rect = new Rectangle();
                    rect.Fill = Brushes.White;
                    rect.Stroke = Brushes.Black;
                    rect.StrokeThickness = 50;
                    rect.Width = (sz.In.EndPosition - sz.In.StartPosition);
                    rect.Height = lineWidth;

                    // Set left coordinate depending on seat zone start position.
                    Canvas.SetLeft(rect, sz.In.StartPosition);
}

und möchte das nun in nen Backgroundworker auslagern, dann springt er mir selbstverständlich bei "rect = new Rectangle();" raus mit dem Fehler, dass die "Design-Principles" verletzt wurden. Die Methode Draw() füllt aber prinzipiell das Canvas der Klasse in der sich Draw() befindet und auf diesem Canvas klebt ein Binding von der GUI.

Das was hier lange dauert ist das erzeugen hunderter Rectangles und das nachträgliche setzen und Berechnen der Position. Und wenn ich jede GUI-Zeile per Invoke verlagere, kann ich mir den Backgroundworker ja gleich sparen und wäre wieder beim GUI-Blockieren-Problem 🙁

29.01.2013 - 13:19 Uhr

Hallo zusammen =),

ich habe eine relativ simple prinzipielle Frage:

Ich möchte in einem Canvas eine durchaus komplexe "Zeichnung" mit vielen Rectangles etc. erstellen. Dies möchte ich natürlich nicht im GUI-Thread machen, was habe ich für Alternativen?

Da ich ja "fast" in jeder Zeile von dem Grafikkonstrukt - welches ausgelagert werden soll - GUI-Elemente erstelle und diese technisch nicht im Backgroundworker erstellt werden können bzw. es kann generell nicht mit ihnen gearbeitet werden, da auch die Methoden der Klassen dies "nicht abkönnen" (Dispatcher-Abhängigkeit), bin ich ziemlich aufgeschmissen. Das Zeichnen dauert jetzt noch ca. eine halbe Sekunde, später evtl. länger.

Es muss doch eine Möglichkeit geben im Falle eines solchen Vorhabens den GUI-Thread nicht zu blockieren? 🤔

Bin für jeden Tipp dankbar.

Grüße

20.11.2012 - 16:42 Uhr

Oman, das ist peinlich 8o
Vergessen! Das INotify habe ich nachträglich eingebaut, weil mir irgendwann in den Sinn kam, dass IDataError nur bei Änderung aktiv wird. Und durch den Versuch mit der Exception-Variante ist mir das nicht aufgefallen, dass dort Nofity fehlt. Ich bin aber zeitgleich mit dem Posting fast selbst drauf gekommen, weil ich für PCStatus einen Converter eingebaut habe, der natürlich aktiv wird und somit war plötzlich auch das Grid (selbst ohne Notify in der Klasse) informiert. Aber prinzipiell fehlt es natürlich da! Danke. 🙂

20.11.2012 - 14:34 Uhr

Hey,

leider auch nicht. Das ist echt merkwürdig. Ich hab schon 100 Varianten durch. X(

Was ich möchte ist folgendes: Ich hab ein DG (readonly!), das zeigt wenige Spalten an und wenn eine Property in dem Objekt, was in Form einer ObservableCollection als Source an dem DG klebt einen bestimmten Wert hat, dann soll die Spalte mit dem Error entsprechend angezeigt werden. Allerdings ohne Usereingaben, denn das DG ist readonly. Es soll sofort angezeigt werden sobald sich das DG füllt.

So sieht das DG aus:


<!--  PC List  -->
                                <tk:DataGrid Name="dataGrid_PCList"
                                             MaxHeight="200"
                                             Margin="6"
                                             AutoGenerateColumns="False"
                                             CanUserResizeColumns="False"
                                             CanUserResizeRows="False"
                                             IsReadOnly="True"
                                             
                                             ItemsSource="{Binding Path=PCList,
                                                                   RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                                  AncestorType=Window}}">
                                    <!--RowStyle="{StaticResource PCListRowStyle}"-->
                                    <!--<tk:DataGrid.RowValidationRules>
                                        <val:RowDataInfoValidationRule ValidationStep="ConvertedProposedValue"/>
                                    </tk:DataGrid.RowValidationRules>-->
                                    
                                    <tk:DataGrid.Columns>
                                        <tk:DataGridTemplateColumn>
                                            <tk:DataGridTemplateColumn.CellTemplate>
                                                <DataTemplate>
                                                    <Image Width="15"
                                                           Height="15"
                                                           Source="{Binding ImageURL}" />
                                                </DataTemplate>
                                            </tk:DataGridTemplateColumn.CellTemplate>
                                        </tk:DataGridTemplateColumn>
                                        <tk:DataGridTextColumn Width="Auto"
                                                               Binding="{Binding Path=Name}"
                                                               Header="Name" />
                                        <tk:DataGridTextColumn Width="Auto"
                                                               Binding="{Binding Path=Status, ValidatesOnDataErrors=True}"
                                                               Header="Status" />                                        
                                    </tk:DataGrid.Columns>
                                </tk:DataGrid>

Und so sieht die gesamte Klasse aus:


/// <summary>
    /// Represents an power copy item in the datagrid.
    /// </summary>
    public class PCStatusItem : INotifyPropertyChanged, IDataErrorInfo
    {
        string _ImageURL;
        /// <summary>
        /// Gets the url of the image.
        /// </summary>
        public string ImageURL
        {
            get { return _ImageURL; }
            private set
            {
                this._ImageURL = value;
                OnNotifyPropertyChanged("ImageURL");
            }
        }

        string _Status;
        /// <summary>
        /// Gets the item status as long text info.
        /// </summary>
        public string Status
        {
            get { return _Status; }
            private set
            {
                this._Status = value;
                OnNotifyPropertyChanged("Status");
            }
        }

        string _Name;
        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set
            {
                this._Name = value;
                OnNotifyPropertyChanged("Name");
            }
        }

        PCStatus _PCStatus;
        /// <summary>
        /// Gets the status of the PC.
        /// </summary>
        public PCStatus PCStatus
        {
            get { return _PCStatus; }
            set
            {
                this._PCStatus = value;

                //if (PCStatus.Error != null)
                //    throw new Exception("Error.", PCStatus.Error);
            }
        }

        /// <summary>
        /// Constructor.
        /// </summary>        
        /// <param name="pcStatus">Power-Copy status.</param>
        /// <param name="name">Name.</param>
        public PCStatusItem(PCStatus pcStatus, string name)
        {
            this.ImageURL = @"Images\V5_RedBall_trans.png"; //! Annahme fuer alle als standard!
            this.PCStatus = pcStatus;
            this.Name = name;

            switch (pcStatus.Status)
            {
                case PCStatusType.GeometryNaming_Error:
                    this.Status = "Geometry naming error"; 
                    break;
                case PCStatusType.GeosetNaming_Error:
                    this.Status = "Geometrical set naming error"; 
                    break;
                case PCStatusType.Parameter_Error:
                    this.Status = "Parameter error"; 
                    break;
                case PCStatusType.Not_Accessible:
                    this.Status = "Not accessible";
                    break;
                case PCStatusType.NotNeeded:
                    this.Status = "Not needed";
                    this.ImageURL = @"Images\V5_GrayBall_trans.png"; //! Standard ueberschreiben!
                    break;

                case PCStatusType.OK:
                    this.ImageURL = @"Images\V5_GreenBall_trans.png"; //! Standard ueberschreiben!
                    this.Status = "O.K."; break;
            }
        }

        #region [ Property_Changed_Utilities ]
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnNotifyPropertyChanged(String info)
        {
            // Note: Do not forget to add interface "INotifyPropertyChanged" to your class.
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion

        #region [ IDataErrorInfo_Members ]
        //! DO NOT FORGET to implement "IDataErrorInfo" in your class!
        public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    string propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                    {
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                    }
                }

                return error.ToString();
            }
        }

        public string this[string columnName]
        {
            get
            {
                // apply property level validation rules
                if (columnName == "PCStatus")
                {
                    if (PCStatus.Error != null)
                        return PCStatus.Error.ToString();
                }               

                return "";
            }
        }
        #endregion
    }

Wobei die Source in dem Window so definiert ist:


/// <summary>
        /// Gets or sets the list of all power copies which are necessary for the current layout.
        /// </summary>
        public ObservableCollection<PCStatusItem> PCList { get; set; }

Bin ratlos X(

20.11.2012 - 14:05 Uhr

Hey,

bin schon ein Stückchen weiter, aber funktionieren tut es immernoch nicht. Ich habe jetzt beim Hinzufügen einfach mal folgende leere Abfrage gemacht:


PCStatusItem si = new PCStatusItem()
PCList.Add(si);
if (si.Error != null) { };

Diese stößt dann die Error-Methoden an, wie erhofft. Das funktioniert. Ist das so gedacht gewesen mit z. B. einer leeren Abfrage?

Allerdings bekommt das DG davon noch nichts mit. An dem DG klebt dafür folgende ValidationRule:


<tk:DataGrid.RowValidationRules>
                                        <val:RowDataInfoValidationRule ValidationStep="RawProposedValue"/>
                                    </tk:DataGrid.RowValidationRules>


 public class RowDataInfoValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value,
                        CultureInfo cultureInfo)
        {
            BindingGroup group = (BindingGroup)value;

            StringBuilder error = null;
            foreach (var item in group.Items)
            {
                // aggregate errors
                IDataErrorInfo info = item as IDataErrorInfo;
                if (info != null)
                {
                    if (!string.IsNullOrEmpty(info.Error))
                    {
                        if (error == null)
                            error = new StringBuilder();
                        error.Append((error.Length != 0 ? ", " : "") + info.Error);
                    }
                }
            }

            if (error != null)
                return new ValidationResult(false, error.ToString());

            return ValidationResult.ValidResult;
        }
    }

Ich hab auch schon mit ValidationStep experimentiert, aber es führte nichts zum Erfolg. Er führt die ValidationRule nicht aus!

Gefunden habe ich die Variante übrigens hier:

WPF DataGrid Practical Examples - Validation with IDataErrorInfo

20.11.2012 - 13:41 Uhr

Hallo zurück,

okay aber die Error Property habe ich ebenfalls implementiert (ist ja nicht so, dass ich keine Anleitung dazu gelesen hätte 🙂), aber auch dort geht er nicht rein wenn ich meine Collection im Code-Behind erstelle. Oder ich verstehe nicht, was du mir sagen willst. 🤔


public string Error
        {
            get
            {
                StringBuilder error = new StringBuilder();

                // iterate over all of the properties
                // of this object - aggregating any validation errors
                PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
                foreach (PropertyDescriptor prop in props)
                {
                    string propertyError = this[prop.Name];
                    if (propertyError != string.Empty)
                    {
                        error.Append((error.Length != 0 ? ", " : "") + propertyError);
                    }
                }

                return error.ToString();
            }
        }

20.11.2012 - 09:53 Uhr

Hallo zusammen,

ich versuche gerade die Objekt-Validierung IDataErrorInfo mit einem ReadOnly-DataGrid zum Laufen zu bringen, aber die Methode


public string this[string columnName]
        {
            get
            {
                // apply property level validation rules
                if (columnName == "PCStatus")
                {
                    if (PCStatus.Error != null)
                        return PCStatus.Error.ToString();
                }               

                return "";
            }
        }

wird nie aufgerufen. Ich vermute mal, weil keine Änderungen gemacht wurden (gemacht werden können=readonly). Ich möchte aber, dass die Daten auch bei Erzeugung validiert werden und nicht erst wenn ich sie ändere. Das Grid ist readonly und soll es auch bleiben. Geht das nicht mit IDataErrorInfo? Als Source des Grids hängt einfach eine ObservableCollection, die zur Laufzeit Objekte hinzufügt, die beim Erzeugen gleich überprüft werden sollen.

Hoffe es kann mir jmd helfen X(

Dank & Gruß

26.06.2012 - 16:55 Uhr

Ja, habe mir schon gedacht, dass es sich um dieses schon angekündigte Problem handelt. Aber ich steige da bezüglich Komplexität aus. X(

Habe ich eine Chance von dem Objekt an die Member zu kommen oder ist das unmöglich? Das Problem ist ja eigentlich nur, dass ich den Typ nicht vorher festlegen will, das ist alles. 🤔

Echt blöd...

26.06.2012 - 16:02 Uhr

Hallo nochmal,

ich lese nun mit folgendem Konstrukt:


foreach (MemberInfo memberInfo in typeof(Sketch).GetMembers())
            {
                if (memberInfo is ConstructorInfo)
                {
                    // Informationen zum Konstruktor
                    ConstructorInfo constructorInfo = (ConstructorInfo)memberInfo;
                    Console.WriteLine("Konstruktor:");
                    Console.WriteLine(constructorInfo.Name);
                    Console.WriteLine(constructorInfo.Attributes);
                    foreach (ParameterInfo parameterInfo in constructorInfo.GetParameters())
                        Console.WriteLine(parameterInfo.Name + " (" + parameterInfo.ParameterType.FullName + ")");
                }
                if (memberInfo is FieldInfo)
                {
                    // Informationen zum Feld
                    FieldInfo fieldInfo = (FieldInfo)memberInfo;
                    Console.WriteLine("Feld:");
                    Console.WriteLine(fieldInfo.Name + " (" + fieldInfo.FieldType.FullName + ")");
                    Console.WriteLine(fieldInfo.Attributes);
                }
                if (memberInfo is MethodInfo)
                {
                    // Informationen zur Methode
                    MethodInfo methodInfo = (MethodInfo)memberInfo;
                    Console.WriteLine("Methode:");
                    Console.WriteLine(methodInfo.Name + " (" + methodInfo.ReturnType.FullName + ")");
                    Console.WriteLine(methodInfo.Attributes);
                    foreach (ParameterInfo parameterInfo in methodInfo.GetParameters())
                        Console.WriteLine(parameterInfo.Name + " (" + parameterInfo.ParameterType.FullName + ")");
                }
                if (memberInfo is PropertyInfo)
                {
                    // Informationen zum Property
                    PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
                    Console.WriteLine("Eigenschaft:");
                    Console.WriteLine(propertyInfo.Name + " (" + propertyInfo.PropertyType.FullName + ")");
                    Console.WriteLine(propertyInfo.Attributes);
                    // ein Property muss nicht zwingend Getter UND Setter haben!
                    if (propertyInfo.CanRead)
                        Console.WriteLine(propertyInfo.GetGetMethod(true).Name);
                    if (propertyInfo.CanWrite)
                        Console.WriteLine(propertyInfo.GetSetMethod(true).Name);
                }
                Console.WriteLine();
            }

den Typ Sketch aus. Herauskommt folgende Ausgabe:

Methode:
Destructor (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
GetMetaObject (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
IsA (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
IsAKindOf (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
GetImpl (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
SetImpl (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
IsNull (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
IsEqual (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
SurChargeQI (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
ChangeComponentState (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
get_Application (INFITF.Application)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
get_Parent (INFITF.CATBaseDispatch)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
get_Name (System.String)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
set_Name (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName
oNameBSTR (System.String&)

Methode:
GetItem (INFITF.CATBaseDispatch)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract
IDName (System.String&)

Methode:
get_GeometricElements (MECMOD.GeometricElements)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
get_Constraints (MECMOD.Constraints)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
get_Factory2D (MECMOD.Factory2D)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
get_CenterLine (MECMOD.Line2D)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
set_CenterLine (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName
oLine (MECMOD.Line2D)

Methode:
get_AbsoluteAxis (MECMOD.Axis2D)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract, SpecialName

Methode:
GetAbsoluteAxisData (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract
oAxisData (System.Array)

Methode:
SetAbsoluteAxisData (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract
iAxisData (System.Array)

Methode:
OpenEdition (MECMOD.Factory2D)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
InverseOrientation (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Methode:
Evaluate (System.Void)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, Abstract

Eigenschaft:
Application (INFITF.Application)
None
get_Application

Eigenschaft:
Parent (INFITF.CATBaseDispatch)
None
get_Parent

Eigenschaft:
Name (System.String)
None
get_Name
set_Name

Eigenschaft:
GeometricElements (MECMOD.GeometricElements)
None
get_GeometricElements

Eigenschaft:
Constraints (MECMOD.Constraints)
None
get_Constraints

Eigenschaft:
Factory2D (MECMOD.Factory2D)
None
get_Factory2D

Eigenschaft:
CenterLine (MECMOD.Line2D)
None
get_CenterLine
set_CenterLine

Eigenschaft:
AbsoluteAxis (MECMOD.Axis2D)
None
get_AbsoluteAxis

Jetzt habe ich allerdings oben den Typ "Sketch" explizit definiert (das möchte ich ja nicht, da es dynamisch sein soll). Ich habe nun ja meine Liste bzw. mein Dictionary mit den Objekten vom Typ Sketch (unter Anderem) und wenn ich nun die Methode GetType() auf ein Objekt vom Typ Sketch ausführe - der Schleifenbeginn sieht folgendermaßen geändert aus:


foreach (MemberInfo memberInfo in this.AllElements.First().Value.GetType().GetMembers())

, um genau obige Ausgabe zu erhalten, damit ich auf die Methoden per Reflection zugreifen kann, bekomme ich jedoch nur folgende Ausgabe:

Methode:
GetLifetimeService (System.Object)
PrivateScope, Public, Final, Virtual, HideBySig, VtableLayoutMask, HasSecurity

Methode:
InitializeLifetimeService (System.Object)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, HasSecurity

Methode:
CreateObjRef (System.Runtime.Remoting.ObjRef)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask, HasSecurity
requestedType (System.Type)

Methode:
ToString (System.String)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask

Methode:
Equals (System.Boolean)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask
obj (System.Object)

Methode:
GetHashCode (System.Int32)
PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask

Methode:
GetType (System.Type)
PrivateScope, Public, HideBySig

Es fehlen also die wichtigen Member. Vor allendingen sind das die, die mich interessieren und welche auch public sind. Wenn ich mir die Definition von Sketch anschaue (es ist ein COM-Typ), dann sieht das folgendermaßen aus:


namespace MECMOD
{
    [TypeLibType(4160)]
    [Guid("EE3021B2-3B09-11D1-A26C-0000F87546FD")]
    public interface Sketch : AnyObject
    {
        [DispId(1610940421)]
        Axis2D AbsoluteAxis { get; }
        [DispId(1610874880)]
        Application Application { get; }
        [DispId(1610940419)]
        Line2D CenterLine { get; set; }
        [DispId(1610940417)]
        Constraints Constraints { get; }
        [DispId(1610940418)]
        Factory2D Factory2D { get; }
        [DispId(1610940416)]
        GeometricElements GeometricElements { get; }
        [DispId(1610874881)]
        CATBaseDispatch Parent { get; }

        [TypeLibFunc(65)]
        [DispId(1610743817)]
        void ChangeComponentState();
        [DispId(1610940425)]
        void CloseEdition();
        [DispId(1610743808)]
        [TypeLibFunc(65)]
        void Destructor();
        [DispId(1610940427)]
        void Evaluate();
        [DispId(1610874882)]
        string get_Name();
        [DispId(1610940422)]
        void GetAbsoluteAxisData(Array oAxisData);
        [TypeLibFunc(65)]
        [DispId(1610743812)]
        void GetImpl();
        [DispId(1610874884)]
        CATBaseDispatch GetItem(ref string IDName);
        [DispId(1610743809)]
        [TypeLibFunc(65)]
        void GetMetaObject();
        [DispId(1610940426)]
        void InverseOrientation();
        [TypeLibFunc(65)]
        [DispId(1610743810)]
        void IsA();
        [TypeLibFunc(65)]
        [DispId(1610743811)]
        void IsAKindOf();
        [TypeLibFunc(65)]
        [DispId(1610743815)]
        void IsEqual();
        [TypeLibFunc(65)]
        [DispId(1610743814)]
        void IsNull();
        [DispId(1610940424)]
        Factory2D OpenEdition();
        [DispId(1610874882)]
        void set_Name(ref string oNameBSTR);
        [DispId(1610940423)]
        void SetAbsoluteAxisData(Array iAxisData);
        [TypeLibFunc(65)]
        [DispId(1610743813)]
        void SetImpl();
        [TypeLibFunc(65)]
        [DispId(1610743816)]
        void SurChargeQI();
    }
}

Es ist also ein Interface. Nun habe ich jedoch auch schon viele andere Konstrukte probiert, u. A. mit der Library "Fasterflect" und auch damit komme ich, egal welche Parameter ich übergebe, nicht an diese Member.

Bin langsam ratlos X(

22.06.2012 - 09:52 Uhr

Ja, das sieht nach einer Lösung für mich aus. 8)

Nur noch einbauen 8o

22.06.2012 - 09:27 Uhr

Hi Profis,

ich habe eine - für mich zumindest - etwas schwierige Frage, die ich mir ohne weiteres nicht beantworten kann. Ich habe eine Liste, welche Elemente vom Typ "object" enthält, also List<object> elements;

Ich möchte nun alle Elemente dieser Liste durchgehen und alle Properties der Elemente in der Liste analysieren, wobei ich NICHT weiß, welcher Typ sich in der Liste befindet. Ich möchte auch keinen Cast durchführen mit einer Case-Anweisung o. Ä. aus dem Grund, dass ich dann die Klassen dadrin beschreiben muss. Es können ca. 200 verschiedene Typen sein (aus dem COM von einem anderen Programm), die jeweils auch mal eine Property, die mich interessiert, aber auch mal 20 Properties haben können, die ich durchsuchen muss.

Das logische Konstrukt, was ich mir vorstelle, damit das vielleicht etwas einfacher zu verstehen ist sieht so aus:


class X
    {
        List<object> Elements { get; private set; }

        public X()
        {
            this.Elements = new List<object>();
        }

        public void Scan()
        {
            // Liste befüllen, dabei sollen die Objekte nicht genau definiert werden.
            this.Elements.Add(new FileInfo("test.txt"));
            this.Elements.Add(new MyObj("test.txt"));
        }

        public List<object> GetObjectsFromAllElementsWithMatchFilter(string filter)
        {
            foreach (var e in this.Elements)
            {
                // Hier möchte ich zb. nach "test.txt" suchen und zwar in ALLEN Properties von allen unbekannten Objekten in der Liste "Elements".
                // Reflection?
                foreach (var prop in AllenPropertiesVonDiesemUnbekanntenObject)
                {
                    if (prop.XXX == filter)
                        yield return e;
                }  
            }
        }
    }

    internal class MyObj
    {
        public string MyProp { get; set; }

        public MyObj(string n)
        {
            this.MyProp = n;
        }      
    }

Kann mir da jmd helfen?
Vielen Dank 🙂

12.04.2012 - 16:22 Uhr

Für alle die nun auf diesen Thread stoßen, meine temporäre Lösung:

Ich lösche mit Hilfe folgender Methoden nun die betroffenen Zeilen einfach heraus und sicherer mir mein Originaldokument vorher ab, damit ich den Ausgangszustand immer bei Bedarf wieder herstellen kann.


#region [ WPF_RichTextBox_Stuff ]
        /// <summary>
        /// Deletes all complete lines which include the 'searchString' from the richtextbox content.
        /// </summary>
        /// <param name="rtb">The richtextbox object.</param>
        /// <param name="searchString">The search string (case sensitive).</param>
        public static void DeleteLinesFromRTB(RichTextBox rtb, string searchString)
        {
            // Find first position of the searchString.
            TextPointer tp = FindWordFromPosition(rtb.Document.ContentStart, searchString);

            while (tp != null)
            {
                // If searchString was found.

                // Determine the offset for the first instance of the new line char befor the current text pointer.
                TextRange tempRange = new TextRange(rtb.Document.ContentStart, tp);
                int lastNewLineSymbolIndex = tempRange.Text.LastIndexOf('\r');
                int beginLineSymbolOffset = tempRange.Text.Length - lastNewLineSymbolIndex;

                // Define the complete line text range.
                TextRange myRange = new TextRange(
                    tp.GetPositionAtOffset(beginLineSymbolOffset * (-1)), // Inverting the index.
                    tp.GetPositionAtOffset(tp.GetTextRunLength(LogicalDirection.Forward)));

                // Deleting the complete line.
                myRange.Text = string.Empty;

                // Rescan the rtb content for further instances of searchString.
                tp = FindWordFromPosition(rtb.Document.ContentStart, searchString);
            }
        }

        /// <summary>
        /// Finds a specific word in a richtextbox position and returns the corresponding text range if word was found.
        /// </summary>
        /// <param name="position"></param>
        /// <param name="word"></param>
        /// <returns></returns>
        public static TextRange FindWordFromPosition_(TextPointer position, string word)
        {
            //? This method came from the www by an individual user.

            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word". 
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        TextPointer start = position.GetPositionAtOffset(indexInRun);
                        TextPointer end = start.GetPositionAtOffset(word.Length);
                        return new TextRange(start, end);
                    }
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // position will be null if "word" is not found. 
            return null;
        }

        /// <summary>
        /// This method returns the position just inside of the first text Run (if any) in a<para>
        /// specified text container.</para>
        /// </summary>
        /// <param name="container"></param>
        /// <returns></returns>
        public static TextPointer FindFirstRunInTextContainer(DependencyObject container)
        {
            //?+ MSDN version.

            TextPointer position = null;

            if (container != null)
            {
                if (container is FlowDocument)
                    position = ((FlowDocument)container).ContentStart;
                else if (container is TextBlock)
                    position = ((TextBlock)container).ContentStart;
                else
                    return position;
            }
            // Traverse content in forward direction until the position is immediately after the opening 
            // tag of a Run element, or the end of content is encountered.
            while (position != null)
            {
                // Is the current position just after an opening element tag?
                if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
                {
                    // If so, is the tag a Run?
                    if (position.Parent is Run)
                        break;
                }

                // Not what we're looking for; on to the next position.
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // This will be either null if no Run is found, or a position just inside of the first Run element in the
            // specifed text container.  Because position is formed from ContentStart, it will have a logical direction
            // of Backward.
            return position;
        }

        /// <summary>
        /// This method will search for a specified word (string) starting at a specified position.<para>
        /// Returns null if word was not found, otherwise the TextPointer.</para>
        /// </summary>
        /// <param name="position"></param>
        /// <param name="word"></param>
        /// <returns></returns>
        public static TextPointer FindWordFromPosition(TextPointer position, string word)
        {
            //?+ MSDN version.

            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word".
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        position = position.GetPositionAtOffset(indexInRun);
                        break;
                    }
                }
                //! This else caused an endless loop.
                //else
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // position will be null if "word" is not found.
            return position;
        }

        /// <summary>
        /// Can get the text from a richtextbox.
        /// </summary>
        /// <param name="rtb"></param>
        /// <returns></returns>
        public static string GetStringFromRichTextBox(RichTextBox rtb)
        {
            var textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
            return textRange.Text;
        } 
        #endregion

PS: Bitte nicht über den Wagenrücklauf ohne Zeilenumbruch wundern, der Logger macht irgendwie komische Zeilenumbrüche. Es hat einfach nicht anders funktioniert. Letzten endes habe ich es einfach experimentell herausgefunden. Ansonsten einfach anpassen.

12.04.2012 - 09:12 Uhr

Ja das Problem ist, dass ich auch "nur über Umwege" überhaupt geschafft habe die NLog-Ausgabe in eine RTB umzuleiten. Dafür waren zusätzliche Klasse notwendig, die ich irgendwo im Netz gefunden habe.

Es ist ja auch so, dass diese schön eingefärbt werden usw. Das soll ja alles so beibehalten werden. Mich nervt es nur, dass wenn das Tool durchlaufen ist ich soviele Trace-Log-Einträge habe, diese brauche ich jedoch aber auch zum Teil, zum anderen Teil nerven sie aber. Daher will ich sie bei Bedarf - und das hinterher - einfach nur für ein paar Sekunden ausblenden.

Ich erkenne, dass das Problem recht schwierig ist. Mehrere RTB mit jeweils einem anderen Inhalt macht für mich überhaupt keinen Sinn, allein schon wegen der Übersichtlichkeit.

🤔

11.04.2012 - 17:41 Uhr

Hi Profis,

ich benutze NLog und lasse mir die Logs in einer RichTextBox anzeigen. Das MinLogLevel ist "Trace", da ich in der RTB alles angezeigt haben möchte.

Nun möchte ich eine Funktionalität hinzufügen, die mir über 6 Checkboxen die verschiedenen Level (Trace, Debug, Info, Warn, Error, Fatal) ein- bzw. ausblendet. Grund: Übersichtlichkeit.

Kann mir da jmd helfen, wie man das anstellen kann? 🙁
Die RTB mit dem Flowdocument ist irgendwie recht komplex.

Mein Ansatz war mit:


TextRange FindWordFromPosition(TextPointer position, string word)
        {
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word". 
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        TextPointer start = position.GetPositionAtOffset(indexInRun);
                        TextPointer end = start.GetPositionAtOffset(word.Length);
                        return new TextRange(start, end);
                    }
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // position will be null if "word" is not found. 
            return null;
        } 

und


TextRange myRange = FindWordFromPosition(this.richTextBox_Log.Document.ContentStart, "TRACE");

irgendwie nach den "Zeilen" zu suchen, aber das hat überhaupt nicht geklappt. Und wenn, dann wüsste ich auch nicht wie man die unsichtbar und wieder sichtbar macht. =)

Vielleicht kann mir dabei ja jmd helfen oder einen Tipp geben 🤔....
Vielen Dank.

28.03.2012 - 13:38 Uhr

Hallo Profis,

ich habe im Codebehind folgenden Target für den NLog:


var target = new WpfRichTextBoxTarget();
            target.Name = "console";
            target.Layout = "${longdate:useUTC=true}|${level:uppercase=true}|${logger}::${message}";
            target.ControlName = "rtbConsole"; // Name of the richtextbox control already on your window 
            target.FormName = "MonitorWindow"; // Name of your window where there is the richtextbox, but it seems it will not really be taken into account, the application mainwindow will be used instead. 
            target.AutoScroll = true;
            target.MaxLines = 100000;
            target.UseDefaultRowColoringRules = false;
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Trace", "DarkGray", "Transparent", FontStyles.Normal, FontWeights.Normal));
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Debug", "Black", "Transparent"));
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Info", "Blue", "Transparent"));
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Warn", "Red", "Transparent"));
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Error", "White", "DarkRed", FontStyles.Normal, FontWeights.Bold));
            target.RowColoringRules.Add(new WpfRichTextBoxRowColoringRule("level == LogLevel.Fatal", "Yellow", "DarkRed", FontStyles.Normal, FontWeights.Bold));

            AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
            asyncWrapper.Name = "console";
            asyncWrapper.WrappedTarget = target;
            SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);

Das klappt auch wunderbar, nur habe ich zusätzlich eine Config-Datei für den NLog, wo weitere Targets drin stehen:


<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- make sure to set 'Copy To Output Directory' option for this file -->
  <!-- go to http://nlog-project.org/wiki/Configuration_file for more information -->

  <variable name="logDirectory" value="${basedir}/logs/${shortdate}"/>

  <targets async="true">
    <!-- all targets in this section will automatically be asynchronous -->

    <!--${newline} generates a new line -->

    <target name="debugFile" xsi:type="File"
            layout="${longdate} LogLevel:${level} ${message} ${exception:Format=tostring}"
            fileName="${logDirectory}/${windows-identity:domain=false}.log"/>

    <target name="traceFile" xsi:type="File"
            layout="${longdate} ${message} ${exception:Format=tostring}"
            fileName="${logDirectory}/${windows-identity:domain=false}_trace.log"/>
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="debugFile" />
    <logger name="*" level="Trace" writeTo="traceFile" />
  </rules>
</nlog>

Nun wollte ich ungern alles zusammenführen und wollte fragen, ob es eine Möglichkeit gibt dem NLogger mitzuteilen, dass er beide Configurations annehmen soll? Denn er präferiert nur die RichTextBox aus dem Codebehind. 🙁

Wäre echt prima, wenn es da etwas geben würde. Ich konnte bisher nichts ausfindig machen.

Gruß

21.03.2012 - 08:39 Uhr

Ok. Vielen Dank. 🙂

20.03.2012 - 17:23 Uhr

Ich habe jetzt scheinbar eine Lösung gefunden, weiß aber nicht, ob die so professionell ist.

Ich habe beim Loaded-Ereignis nun den DataContext auf die Singleton-Instanz gesetzt.


private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = Settings.Instance;

            // Store previous settings for recovering if user presses "Go Back" button.
            prevSettings = Settings.Instance.Clone();
        }

und in XAML die statische source weggenommen:


IsChecked="{Binding Path=IgnoreStringsOnCompare, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Nun muss ich zwar den Datacontext setzen, aber das scheint zu klappen.
Hoffe ich hab kein Denkfehler.

20.03.2012 - 16:06 Uhr

Hallo zurück,

ja, dass kann ich natürlich machen, aber ich will mir soviel Codezeilen, wie möglich, sparen. Dachte es gäbe eine saubere Lösung, als an dieser Stelle alle (was ist wenn es 500 Stück oder mehr sind?) Properties zurück zu schreiben oder gar auf Änderung zu überprüfen. 🙁


oldObj.A = newObj.A;
oldObj.B = newObj.B;
oldObj.C = newObj.C;
...

gefällt mir gar nicht X(

Hier

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.propertychanged.aspx

habe ich gelesen, dass man PropertyChanged für alle Properties mit String.Empty feuern kann. Allerdings funktioniert das glaube ich ja nur, wenn sich wirklich eine Property geändert hat oder?

20.03.2012 - 15:17 Uhr

Hi Profis,

ich habe eine Singleton-Settings Klasse, wo ich in der GUI meine Settings mit zb


IsChecked="{Binding Source={x:Static misc:Settings.Instance},
                                                                  Path=IgnoreStringsOnCompare,
                                                                  Mode=TwoWay,
                                                                  UpdateSourceTrigger=PropertyChanged}"

dran "binde". Jetzt habe ich in dem Settings-Modul einen Apply und einen Zurück Button.

Wenn ich das Settings-Modul lade erzeuge ich via ICloneable-Interface mit


private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            // Store previous settings for recovering if user presses "Go Back" button.
            prevSettings = Settings.Instance.Clone();
        }

einen Klon meiner vorherigen Einstellungen für den Fall, dass der User den zurück Button drückt, statt Apply.

Wenn der User denn den Zurück Button drückt, dann schreibe ich mit


private void button_GoBack_Click(object sender, RoutedEventArgs e)
        {
            // When pressing "Go Back" button, do not store current made settings.
            Settings.Instance = prevSettings;
        }

den lokal statisch gespeicherten Klon zurück bzw. ich hänge die Referenz um. Leider aktualisiert sich das Binding - trotz TwoWay - nicht. Ich denke mal weil er das nicht mitbekommt, da ich lediglich in den Properties der Settings-Klasse "NotifyPropertyChanged" feuer. Prinzipiell brauche ich etwas, was das Binding anstößt. Also ein NotifyPropertyClassChanged oder so =) Zumindest ist das meine Vermutung.

Kann mir da jmd helfen? Das wäre echt klasse.

Viele Grüße

19.03.2012 - 23:55 Uhr

8o Das kannte ich noch nicht, genau das hab ich gesucht. Es bringt mich 50% weiter. Ein Icon wird automatisch aktiviert, wo ich sonst hätte ein Klick machen müssen. Ein paar andere jedoch nicht in einem ganz bestimmten Zustand, aber das habe ich glaub ich selbst verbockt.

Ich vermute da stimmt etwas mit:


Settings.Instance.IsValid

nicht. Es funktioniert zwar (hinterher), aber er scheint in einem ungünstigen Zeitpunkt dort "false" in der Variable drin zu haben und dann keine Aktualisierung mehr zu machen, solange ich jedenfalls nicht wohin klicke. Ich habe Settings.Instance.IsValid über IDataError realisiert und mit Hilfe dieses Ansatzes:

http://www.codeproject.com/Articles/14178/Delegates-and-Business-Objects

Und ich weiß jetzt nicht wo ich


CommandManager.InvalidateRequerySuggested()

dort ausführen könnte. Zumal ich auch diese IDataError-Geschichte mit den Rules in eine Library ausgelagert habe und dort natürlich keinen CommandManager habe. Ich könnte höchstens ein Event feuern, aber ob das so gut ist? Bin mir auch nicht 100%ig sicher, ob das überhaupt das Problem ist.

Aber auf jeden Fall war CommandManager.InvalidateRequerySuggested() ein Klasse Hinweis!
Vielen Dank.

19.03.2012 - 23:01 Uhr

Ja sorry, dachte mir, dass das nur Verwirrung stiftet, weil ich im Code nix besonderes mache.

Meine Toolbar (Ausschnitt):


<!--  Toolbar  -->
        <ToolBarTray Name="toolBarTray_MainToolBar"
                     Grid.Row="2"
                     Background="WhiteSmoke">
            <ToolBar>
               <Button Name="button_CompareFiles"
                        Command="{x:Static mc:MyCmds.CompareFiles}"
                        ToolTip="Compares the selected compressed calendar files.">
                    <Image Source="Images\Compare.ico" />
                </Button>
            </ToolBar>
        </ToolBarTray>

Meine Menubar (Ausschnitt):


<!--  Menu bar  -->
        <Menu Name="menu_MenuBar"
              Grid.Row="1"
              >
            <MenuItem Header="_Data">
               <MenuItem Name="menuItem_CompareFiles"
                          Command="{x:Static mc:MyCmds.CompareFiles}"
                          Header="_Compare files"
                          InputGestureText="Ctrl+C"
                          ToolTip="Compares the selected compressed calendar files.">
                    <MenuItem.Icon>
                        <Image Source="Images\Compare.ico" />
                    </MenuItem.Icon>
                </MenuItem>
            </MenuItem>
        </Menu>

Style, um Image vor dem deaktivierten Menu- & Toolbaritem ebenfalls zu "deakivieren":


<Style TargetType="Image">
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Opacity" Value="0.2" />
                </Trigger>
            </Style.Triggers>
        </Style>

Dann ein Beispielhandler für CanExecute:


CommandBinding cb_CompareFiles = new CommandBinding(MyCmds.CompareFiles, CompareFilesHandler);
            cb_CompareFiles.CanExecute += (object sender, CanExecuteRoutedEventArgs e) =>
            {
                e.CanExecute = (this.filesScanned && Settings.Instance.IsValid) ? true : false;
            };

Jetzt starte ich einfach einen Backgroundworker, der ca. 5sek etwas tut und kurz bevor ich


bgw_ScanFiles.RunWorkerAsync();

aufrufe sage ich: this.filesScanned=false, um zb. die Compare-Funktion zu deaktivieren und wenn der CompletedHandler des Workers aufgerufen wird mache ich this.filesScanned=true.

Aber DANN muss ich immer erst einmal irgendwo im Programm klicken, bevor zb. die Toolbarimages wieder aktiviert werden. 🤔

19.03.2012 - 21:07 Uhr

Hallo Profis,

ich habe eine WPF Applikation in welcher ich mit Commands meine Toolbar mit Icons aktiviere und deaktiviere. Das mache ich mit der Opacity-Eigenschaft und der IsEnabled-Eigenschaft.

Allerdings gibt es ein merkwürdiges Phenomän, welches ich mir nicht erklären kann: Immer wenn ich zb. einen Backgroundworker starte - vorher dann eine Variable, die mit CanExecute überprüft wird auf isRunning=true setze, werden alle Buttons im Menu und die Icons in der Toolbar entsprechend über die Commands deaktiviert. Das funktioniert! Wenn nun aber der Completed-Handler des Workers erreicht wird und die Variable isRunning=false gesetzt wird, muss ich immer einmal irgendwo hinklicken, bis die Icons in der Toolbar refreshed werden und somit aktiviert sind. Das ist echt blöde und nervt und wirkt ziemlich unprofessionell.

Vielleicht mache ich das auch irgendwie falsch? Muss man CanExecute oder die GUI-Commands nochmal manuell irgendwie anstoßen oder dergleichen?

Bin für jeden Tipp dankbar.

Grüße

13.03.2012 - 17:13 Uhr

Ach herje das ist ja wirklich total easy oman. Danke!

Ich hab gedacht, dass ich das schon habe, nämlich im Style mit "AdornedElementPlaceholder", aber das ist was anderes. Dann stimmt das doch, was ich da gelesen habe im Beitrag. Habs nur missverstanden. =)

Dankeschön 🙂

07.03.2012 - 10:51 Uhr

Die Codeblöcke in der Toolbox lassen sich über die Settings von Visual Studio exportieren, sie befinden sich unter "Toolbox".

Das Addin läuft nun auch, aber es ist nicht wirklich praktikabel. Ziel ist es immernoch den Snippet-Designer für XAML zum laufen zu bringen.

06.03.2012 - 19:02 Uhr

Hi Profis,

ich habe ein unschönes Problem. Ich habe ein WPF-Window, welches in der Mitte aufgeteilt ist. Im Rechten Bereich wechsle ich immer UserControls. Ein UC ist ein SettingsUC. Dort habe ich eine Settings-Klasse hinterlegt in welcher ich IDataErrorInfo implementiert habe. Funktioniert auch soweit alles wunderbar. Wenn ich aber ein Error provoziere und dann ein anderes UC anzeige und dann das UC mit dem Error, dann ist der Error plötzlich verschwunden und ich muss erst wieder ein anderes Zeichen eingeben und dann wieder ein "Problemzeichen", um den Error wieder angezeigt zu bekommen. Es sieht nach diesem Problem aus (im Netz gefunden):

http://social.msdn.microsoft.com/Forums/en/wpf/thread/b90114e5-f6cc-4ad5-9916-89ccdccecd35

Leider konnten mir die Antworten nicht weiterhelfen. Beim UserControl-Load-Event folgendes zu schreiben


textBox_CompareDelay.GetBindingExpression(TextBox.TextProperty).UpdateSource();

hat leider auch nichts gebracht, finde ich nebenbei aber auch sehr unschön. Weiterhin hätte ich es auch gerne - neben einer Lösung dieses Problems natürlich =) - dass alles blockiert wird solange bis ein vernünftiger Wert in das jeweilige Feld eingegeben wird. Überall lese ich immer, dass zur Nutzung von IDataErrorInfo geraten wird, anstatt irgendwelche ValidationRules zu erstellen, dabei sehe ich da bisher nur Probleme.

Kann mir da jmd einen Tipp geben, wie ich zumindest beim Laden eine Validierung hinbekomme, so dass der Error wenigstens angezeigt wird? Wäre echt klasse.

Mein Errortemplate sieht folgendermaßen aus:


<!--Textbox error style-->
    <Style x:Key="TextBox_ErrorStyle" TargetType="{x:Type TextBox}">
        <Setter Property="VerticalAlignment"
                Value="Center" />
        <Setter Property="Margin"
                Value="0,2,40,2" />
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="true">
                        <Border Background="Red"
                                DockPanel.Dock="Right"
                                Margin="5,0,0,0"
                                Width="20"
                                Height="20"
                                CornerRadius="10"
                                ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                            <TextBlock Text="!"
                                       VerticalAlignment="Center"
                                       HorizontalAlignment="Center"
                                       FontWeight="Bold"
                                       Foreground="White">
                            </TextBlock>
                        </Border>
                        <AdornedElementPlaceholder Name="customAdorner"
                                                   VerticalAlignment="Center">
                            <Border BorderBrush="Red"
                                    BorderThickness="1" />
                        </AdornedElementPlaceholder>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
       </Setter>
    </Style>

Auch hier habe ich mal testweise einen Trigger auf "HasError" gelegt, brachte aber auch keinen Erfolg. X(

Bin echt am verzweifeln....

Vielen Dank schon mal...

Grüße

15.02.2012 - 18:36 Uhr

Hi Profis,

ich bin dabei mir einige Snippets zurecht zu legen, so dass ich einfach schneller beim programmieren bin. In Codebehind in C# klappt das auch alles super (Snippet Designer Addin + Shortcuts). Ich kann also gleich mit dem Intellisense filtern und einfügen. Das gleiche möchte ich jedoch auch in XAML haben. Angeblich funktioniert es wie hier beschrieben:

Verwenden von XML Snippets

Wenn man nun aber mal genauer liest 😁 ist das nur für XML gedacht, was natürlich (zumindest für mich) völlig X( ist. Jetzt bin ich weiterhin auch auf

http://xamlcodesnippets.codeplex.com/

gestoßen, was ich jedoch nicht wirklich zum Laufen bringen konnte 🙁 Auf der anderen Seite - wenn es denn läuft - ist es dort so , dass ich aus einer großen Liste dann aussuchen muss. Habe ich 100 Snippets kann ich es auch gleich selbst schreiben, da der Filtermodus nicht existiert.

Dann habe ich noch ein Weg über das "reinziehen" von Codeböcken in die Toolbox gefunden, was mir aber nicht gefällt, da ich ebenfalls suchen muss und weiterhin nicht weiß, wo die Snippets abgelegt werden (würde mich im übrigen auch interessieren wo die gespeichert werden).

Ich hätte es am liebsten, dass die angepriesene XML Ausschnitts-Visual-Studio-Funktionalität in XAML genauso funktioniert wie in XML oder im Codebehind.

Kann mir da jmd helfen oder mir einen Tipp geben? Wäre echt weltklasse!

8o

13.01.2012 - 13:15 Uhr

Ah ok. Habe ich gemacht und teste gerade mal ein bisschen. Sieht so aus als hätte es zumindest so 20-35% gebracht. 👍

Ich werde jetzt mal die Timestamps auslagern in eine weitere Tabelle. Mal sehen, ob das noch etwas bringt. Zumindest sollte sie dann ja weniger Speicher verbrauchen.

13.01.2012 - 12:55 Uhr

Ok das klingt natürlich logisch. Danke für die Erklärung. Ein Index sagt mir natürlich was, nur in diesem Zusammenhang bin ich mir nicht sicher, wie ich diesen einrichte. Die Tabelle sieht so aus ...vgl. Anhang (Screenshot aus dem Visual Studio Datenquellenmanager)

PS: Linqpad schau ich mir mal an, sieht sehr nützlich aus.

13.01.2012 - 11:33 Uhr

Ok linqpad sagt mir jetzt gar nichts. Habe kein SQL-Server inkl. Management Studio.

Meinst du mit Index erstellen, den Timestamp in eine separate Tabelle auszulagern? Wird Datetime nicht intern nur als Fließkomma gespeichert? Lohnt sich das? Für ca. 100 Zeilen jeweils in der einen Haupttabelle habe ich immer denselben Timestamp => Redundanz.

13.01.2012 - 10:36 Uhr

Hi,

na klar:


var queryUserLines = (from userLine in tabUserL
                                              where _consideredFeatureNames.Contains(userLine.FeatureName.ToUpper()) &&
                                              userLine.Timestamp >= _from && userLine.Timestamp <= _to
                                              select userLine).ToList();

Die Tabelle tabUserL hat 1.400.000 Einträge (Einemillionvierhunderttausend). =)

Diese Abfrage dauert ca. 30 Sekunden.

13.01.2012 - 09:25 Uhr

Weil es viele Informationen sind vielleicht. Hätte jedenfalls nicht gedacht, dass sie gleich 1,5 mal so groß ist wie die summierte Textfilegröße.

Mit parsen meine ich Zeile für Zeile durchgehen und die Infos in Objekte schreiben und mit diesen dann arbeiten. Das dauert bei der DB-Abfrage genausolange wie wenn ich die Textfiles durchgehe. Und bezüglich Speicher ist genau dies das Problem. Es ist ein Windows-Service und die Speicherauslastung geht bis zu 1GB hoch beim parsen der Textfiles, was inakzeptabel ist.

11.01.2012 - 17:38 Uhr

verwendetes Datenbanksystem: <SQL-Compact mit LINQ2SQL>

Hallo DB-Profis,

ich habe ca. 4 Textdateien a ca. 30-35MB mit jeweils ca. 600.000 Zeilen. Diese muss ich parsen und analysen mit den Daten machen. Um die Zugriffszeit und das Speichermanagement zu verbessern entschied ich mich die Daten in eine SQL-Compact_Datenbank zu speichern. Allerdings zunächst ohne Beziehungen usw. Die Daten sollen nicht weiter zusammengefasst werden und müssen so wie sie sind geparst werden. Was mich verwunderte ist, dass die Textdateien in ihrer Größe aufsummiert ca. 110MB betragen und die Datenbankdatei ca. 170MB aufwies (jede Textdateizeile in eine Datenbankzeile in eine Haupttabelle 1:1). Wie kann das sein? Im schlimmsten Falle habe ich auf gleiche Größe gehofft, im besten vielleicht auf die Hälfte oder ähnliches. Weiterhin ist das Durchlaufen der ganzen Dateien Zeile für Zeile praktisch genausoschnell/genausolangsam (mehrere Minuten) wie die LINQ2SQL-Abfrage auf die Datenbank. X(

Mein nächster Schritt wäre natürlich die Datenbank versuchen zu strukturieren, Redundanzen zu vermeiden usw. Aber das Problem was ich habe ist irgendwie die Aussichtslosigkeit und der Schreck, dass die DB-Datei noch größer ist als die Textdateien zusammen und es überhaupt keinen Performancegewinn bei der Abfrage gegeben hat. 🤔

Wenn ich im Taskmanager schaue, dann steigt die Speichernutzung teilweise auf bis zu 1 GB an. Das ist viel zu viel!

Kann mir da jmd Hilfestellung geben, wie ich die Dateien am besten/schnellsten/einfachsten parse und was das mit der DB auf sich hat?

PS: Um die Gesamtanalyse im Falle der Textdateien zu optimieren (und das ist auch gelungen) habe ich immerhin schon mehrere Threads laufen, die parallel die Dateien Zeile für Zeile parsen. Jedoch insgesamt viel zu langsam und die Speicherauslastung viel zu hoch.

Hoffe mir kann jmd helfen...
Vielen Dank schon mal.

Grüße

09.12.2011 - 13:44 Uhr

Hi Profis,

ich habe schon seit längerem ein "Design-Problem" mit welchem ich bis heute irgendwie nicht so richtig zurecht komme. Vielleicht kann mir ja hier jmd helfen.

Folgendes: Ich hab ein WPF-Window (s. Anhang) und im Window die Property "SizeToContent=true" gesetzt. Als Beispiel sind die Labels

  • Catia V5 input
  • FEM Grid

und die zugehörigen Textboxen und Buttons sind in einem Grid mit 3 Spalten (1 Spalte = beide Labels, 2. Spalte = beide Textboxen , 3. Spalte = beide Buttons) und zwei Zeilen angelegt. Nun haben Spalte 1 und 3 den Wert Auto und Spalte 2 für die Textboxen einen fixen Wert!

Jetzt möchte ich aber die Spalte 2 für die Textboxen in ihrer Breite dynamisch setzen also zb Wert= "1*". Damit erreiche ich, dass wenn sich irgendwas an meiner GUI ändert, ich nicht jedesmal den fixen Wert aktualisieren muss.

Nun habe ich aber ein Problem: Wegen SizeToContent=true wird die GUI extrem in der Breite erhöht, wenn die Textbox einen sehr langen Inhalt bekommt, da er die Textbox wegen der Spaltenbreite="1*" nun dynamisch anpasst und SizeToContent=true ist. D.h. die gesamte GUI wird so breit gezogen, wie der Inhalt der Textbox ist und das wegen SizeToContent=true und Spaltenbreite vom Grid= "1*".

Eine Lösung wäre SizeToContent=false zu setzen, dann wird die Textbox zwar in der Breite erhöht, aber nur so wie ihr Fenster es vorgibt, d.h. bekommt sie einen sehr großen Inhalt, katapultiert sich das gesamte Window nicht in die Breite. Nachteil aber ist, dass ich die Fenstergröße vorher mit festen Pixeln angeben muss und das stört mich gewaltig, da ich das experimentell herausfinden muss X(

Meine Frage: Wie macht man sowas richtig und/oder gibt es dafür eine Lösung, wo ich die Fenstergröße nicht vorgeben muss, diese sich automatisch dem Inhalt anpasst und die Textboxen wegen ColumnWidth="1*" des Grids sich nicht in die Breite katapultieren, wenn sie einen sehr großen Inhalt bekommen? 🤔

Bin da für jeden Tipp dankbar.

24.11.2011 - 12:54 Uhr

Es sind so 170-190 Zeilen und 30 selbsterstellte Spalten, wobei u.a. TemplateColumns drin sind (AutoGenerateColumns=false). Die TemplateColumns habe ich aber auch mal testweise durch TextColumns ersetzt und das Problem besteht weiterhin.

Data-Virtualization sagt mir jetzt gar nichts. Hmmm. Muss ich mal googeln 8o

Was mich nur nervt ist, dass das eigentlich wirklich wenig Zeilen sind und ich schon mehr Zeilen in nem DataGrid gesehen habe und dort ging das Sortieren auch total schnell 🙁
Es scheint aber bei mir eher irgendein Anzeige oder Bindingproblem zu sein, denn das Sortieren an sich geht ja schnell, das habe ich ja gemessen.

24.11.2011 - 09:48 Uhr

Hallo,

ich habe den CustomSorter eingebaut und mal gemessen, wie lange er zum Sortieren benötigt. Das Sortieren dauert weniger als eine Sekunde (gemessen), jedoch benötigt er danach sehr lange, um das anzuzeigen. Und genau dort weiß ich nicht weiter. Es scheint also nicht an dem Sortieralgorithmus zu liegen, sondern an irgendwas anderem.

An jeder Spalte klebt ein Binding an dem jeweiligen Attribut der Klasse. Habe mir mal ein Beispielprojekt angesehen, wo ein CustomSorter implementiert ist und mit dem normalen Standardsort verglichen wurde und der unterschied ist merklich spürbar, jedoch habe ich den CustomSort genauso implementiert und wie bereits beschrieben, geht das auch recht fix, jedoch NACH dem Sortieren dauert es lange. Das ist sehr merkwürdig. 🤔

wie sortierst du denn?

Vorher habe ich einfach den Standardsortieralgorithmus benutzt, d.h. ich habe diesbzeüglich nichts programmiert, es funktionierte sofort ==> DataGrid-Funktionalität.

22.11.2011 - 18:03 Uhr

Hi Profis,

ich sitze an einem hässlichen Problem und finde einfach keine Lösung dazu. Evtl. fehlt mir einfach der Hintergrund.

Folgendes: Ich habe ein WPF-Datagrid und die Spalten sind mit einem Binding an einer Klasse dahinter verbunden. Das klappt alles soweit perfekt, jedoch gibt es ein Problem. Wenn die Liste sehr groß wird, dann dauert insbesondere das Sortieren einer Spalte sehr sehr lange. X(

Das kann ich nicht so lassen, da es mehrere Sekunden dauert in Abhängigkeit natürlich von der Größe der Liste. Ist das ein Bekanntes Problem oder gibt es dafür Lösungswege, die man einschlagen kann?

Bin für jeden Tipp sehr dankbar.

PS: Eine Sache, die ich im I-Net gefunden habe war, dass man - falls man eine Liste hat als Source, lieber eine ObservableCollection nehmen sollte, da diese von der Performance her besser ist. Um genau zu sein 20ms zu 1600ms Zugriffszeit habe ich gelesen. Leider hat mir das aber auch nichts gebracht komischerweise 🙁

Anmerkung: Das Grid ist nur um anzeigen, nicht zum ändern der Werte da. D.h. alles ist readonly! Die Setter/Getter an denen das Binding klebt erledigen keine Aufgaben! Der Variablenwert wird nur jeweils gesetzt bzw nur ausgelesen/zurückgegeben.

16.11.2011 - 12:31 Uhr

Ok für alle die, die auf diesen Thread durch eine Suche gestoßen sind und sich ebenfalls über die Leute aufregen die dann nur schreiben: closed, weil gelöst 🙄 8o

Folgendes hat mir weitergeholfen:

Ich habe (in Visual Studio 2010 Pro) ein neues Element hinzugefügt ==> Anwendungsmanifestdatei und dort


<requestedExecutionLevel  level="asInvoker" uiAccess="false" />

durch


<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

ersetzt. Die Vorlagen sind dort schon alle vorhanden, man muss sich praktisch nur "einkommentieren". Das löst das Problem in sofern, dass beim Start der kompletten Applikation die UAC auftaucht und nach dem Admin fragt und anschließend die gesamte App als Admin läuft. Dadurch kann ich auch wieder den Output umleiten ohne das die Fehlermeldung kommt, dass useshellexecute=true sein muss.

PS: Es funktioniert scheinbar nicht (zumindest bei mir nicht), die App ohne Adminmanifest - also ganz normal wie vorher - über Windows dann mit einem Rechtklick auf die EXE und "Als Administrator ausführen" zu starten.

Also alles bestens 😁

Dankeschöööön.

Grüße

15.11.2011 - 18:30 Uhr

Hi Profis,

ich habe folgendes Problem und kriege es einfach nicht hin:

Ich möchte ein Prozess mit Parametern als Admin starten (Windows 7) und parse den Output, den ich an die Konsole weiterleite. Daher ist:


System.Diagnostics.Process startServiceProcess = new System.Diagnostics.Process();

                            startServiceProcess.EnableRaisingEvents = true;
                            startServiceProcess.StartInfo.UseShellExecute = false;
                            startServiceProcess.StartInfo.CreateNoWindow = true;
                            startServiceProcess.StartInfo.RedirectStandardError = true;
                            startServiceProcess.StartInfo.RedirectStandardOutput = true;

Jetzt habe ich:


                            if (System.Environment.OSVersion.Version.Major >= 6)  // Windows Vista or higher
                            {
                                startServiceProcess.StartInfo.Verb = "runas";
                            }
                            else
                            {
                                // No need to prompt to run as admin
                            }

dahinter eingefügt. Anschließen den Process gestartet. Das Funktioniert nur, wenn


UseShellExecute = true

ist. Dann habe ich aber das Problem, dass ich den Output nicht parsen kann, was wichtig ist. Und wenn ich UseShellExecute = false setze und den Username, Domäne und PW in den Code direkt eingebe funktioniert es, jedoch habe ich dann das "WindowsBehaviour" nicht, d.h. Automatische Eingabe - falls erforderlich - von User + PW des Adminkontos.

Wie kann ich den Output parsen d.h. UseShellExecute = false und gleichzeitig die Windows-Adminabfrage (UAC) verwenden? 🤔

Das Ärgert mich wirklich. Ich möchte mir jetzt eigentlich keinen Dialog basteln und nach dem PW verlangen sondern das - wie eigentlich gedacht - Windows selbst überlassen.

Hoffe mir kann da jmd helfen, bin echt am verzeifeln. 🙁

Bin dankbar für jeden Hinweis...

11.11.2011 - 16:40 Uhr

Hallo,

also ich hab mir das schon gedacht mit Clickonce.

Habe das gerade mal ausgiebig getestet und es war leider nicht möglich - trotz Deaktivierung der Überprüfung auf erforderlichen Komponenten - ein Setup auf verschiedenen Rechnern zu installieren. Teilweise kam leider die Meldung, dass Adminrechte erforderlich sind. Tjo, also kommt Clickonce nicht in Frage. Was positiv ist: Der Updatemechanismus, wenn es installiert werden konnte und die Eigenschaft, dass in der Verknüpfung auf dem Desktop der Zielpfad nicht ersichtlich ist.

Allerdings habe ich hier das Problem, dass ich in der AssemblyInfo-Datei die Version händisch hochzähle zb. "1.0.*" und ich dann - im Fall von Clickonce - noch eine weitere Publikationsversion manuell definieren muss (Das automatische Auslesen der Publikationsversion und Anzeigen im Hauptprogramm a la AssemblyVersion) hat leider nicht funktioniert. So müsste ich immer ein weiteres Feld mit dem String in der Datei "AssemblyInfo" synchron halten.

Da war ich mit meinem eigenen Launcher schon besser bedient.

PS: Das mit der Schattenkopie klappt leider immernoch nicht (s. o.) 🙁

10.11.2011 - 15:36 Uhr

Moin,

leider komme ich mit den ShadowCopies nicht weiter denn ich bekomme bei der Ausführung der Methode


domain.ExecuteAssembly(assembly);

immer folgenden Fehler:

Fehlermeldung:
Die Datei oder Assembly "file:///I:...\001_Applikationen\007_Launcher\Launcher\bin\Debug\Launcher.exe" oder eine Abhängigkeit davon wurde nicht gefunden. Der Vorgang wird nicht unterstützt. (Ausnahme von HRESULT: 0x80131515)

In der InnerException steht ein Hinweis, dass er nicht von einer Netzwerkadresse laden kann. Daraufhin habe ich gemacht, was da steht und das war in der Konfigurationsdatei folgendes einfügen:


<runtime>
    <loadFromRemoteSources enabled="true"/>
  </runtime>

Gemacht, getan, hat aber leider nichts gebracht. Nach wie vor derselbe Fehler 🙁 Auch wenn ich das nicht vom Netzlaufwerk starte sondern lokal, dann kommt der Fehler auch. Was ist da nur los? Kann mir das echt nicht erklären. In der VisualStudio-Config-Datei deven*.config oder so habe ich bereits vor Tagen ebenfalls diesen Schalter hinzugefügt, weil es sonst nicht möglich ist ohne Fehlermeldung Visual-Studio-Projekte auf dem Netzlaufwerk zu bearbeiten und zu debuggen.

Alles recht komisch, hat da jmd ein Tipp? =)

PS: Hab die Pfade von den Variablen, die an die Klasse AppDomainSetup gehen natürlich schon mehrmals überprüft, die stimmen!

09.11.2011 - 13:29 Uhr

Ja ich probiere es mal aus. Habe gesehen, dass das VZ angegeben werden kann. Im Notfall müsste man eben ein Teil des angemeldeten Users mit in den Verzeichnisnamen aufnehmen oder eine Zufallszeichenfolge oder so etwas. Denn wenn sonst der zweite User die Schattenkopie anlegt, dann würde er ja prinzipiell die erste überschreiben wollen (Annahme = gleiches VZ) und dann wären wir beim alten Problem!

Ich überprüfe das mal!

Danke.

09.11.2011 - 13:21 Uhr

Hi Günther,

das mit den Schattenkopien klingt sehr interessant und nutzbar für mein Problem. Allerdings wie verhält es sich, wenn mehrere User das Programm auf dem Netzlaufwerk starten?

09.11.2011 - 11:57 Uhr

Also bis jetzt ist es so, dass wenn das Programm gestartet wird es halt ein Hinweisfenster gibt und dort steht, dass eine neue Version existiert (wenn das denn so sein sollte). Das funktioniert, weil er den Ordner kennt (der ist fix), wo das Programm liegt bzw die Versionen und jede Version hat einen Ordner mit ner Nummer + Namen und der Ordnername wird geparst und die höchste Version ist natürlich die neueste und wenn diese höher ist als die, die gerade läuft, dann gibt es halt die Meldung.

Danach jedoch muss man die Verknüpfung mauell umlegen und das gefällt mir nicht besonders. X(

Vorteil ist, dass die alten Versionen wie gewohnt funktionieren und ich nicht 100 Jahre warten muss, bis keiner mehr das Programm nutzt sondern einfach für eine neue Version schnell einen neuen Ordner mache und den entsprechend benenne. Weiterer Vorteil: Ich hab keine Probleme mit der IT, da die Jungs lediglich das Programm vom Netzlaufwerk starten und weiterhin weder was installieren müssen, noch irgendwelche Adminrechte brauchen und und und :evil: