سؤال

لدي DataGridView غير المقيد (في VS 2008) ، والذي يحتوي عمود واحد على مسار ملف. أرغب في تنسيق السلسلة باستخدام فئة TextRenderer في حدث ColumnWidThanged دون تعديل القيمة الأساسية فعليًا. المشكلة هي أن محتويات الجدول يتم حفظها عند إغلاق النموذج ولا أريد حفظ القيمة المنسقة. أعتقد أنني في أعماق أن أرى الحل الواضح ، لذا فأنا أعتمد على يا رفاق لإشارةه إلى ذلك :-).

الفكرة هي عرض هذا:

C: Program Files Microsoft Visual Studio 8 SDK V2.0 bin gacutil.exe

... كما هذا (اعتمادًا على عرض العمود):

C: Program Files Microso ... gacutil.exe


يبدو أنني تحدثت في وقت قريب جدا. أحصل على بعض النتائج الغريبة جدًا من Textrenderer.MeasureText (). إذا قمت بتدوين قيمة المسار على أنها "C: Documents and Settings jluce My Documents Downloads" ، فإنه ينتهي كـ C: Documents and Settings Jluce M ... downloads 0wnloads ". T hardcode (مثل أدناه) يتم تالفه في كل مرة أقوم بتغيير حجم العمود.

إليك ما يبدو عليه بعد تغيير حجم الزوجين:لقطة شاشة

إليك ما أفعله حاليًا.

  if (e.ColumnIndex == 1)
  {
    foreach (DataGridViewRow Row in mappingsDataGrid.Rows)
    {
      string Path = (string)Row.Cells[1].Value;
      Path = Path.Trim();

      TextRenderer.MeasureText(Path, e.CellStyle.Font,
        new Size(mappingsDataGrid.Columns[e.ColumnIndex].Width, Row.Height),
          TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);

      e.Value = Path;
    }
  }

هذا مجرد الحفاظ على أغرب !!

تمكنت من إصلاح مشكلة السلسلة المشوهة من خلال التكرار من خلال كل شار وإزالة السيئ. ومع ذلك ، الآن لدي مشكلة أكثر جنونًا. المتغير المحلي أقوم بتعيينه في معالج الأحداث يحتفظ بقيمته بين المكالمات.

إليك الرمز ذي الصلة:

     string Path = ""; // <-- #1
     Path = "C:\\Documents and Settings\\jluce\\My Documents\\Downloads"; // <-- #2

      TextRenderer.MeasureText(Path, Row.Cells[1].Style.Font,
        new Size((mappingsDataGrid.Columns[e.Column.Index].Width), Row.Height),
          TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);

      // Left out code that strips invalid chars

      Row.Cells[1].Value = Path; // <-- #3
      Path = null;

أول مرة في تغيير حجم العمود (ارجع إلى #في التعليقات أعلاه):

  1. بعد هذا الخط يحتوي على "".
  2. بعد هذا السطر ، يحتوي مسار الخط على سلسلة كما يظهر أعلاه.
  3. يحتوي المسار على مسار ملف مقطوع كما ينبغي (أي "C: Documents and Setti ... Downloads")

مرة الثانية تغيير الحجم:

  1. بعد هذا الخط يحتوي على "" "، كما ينبغي.
  2. بعد هذا السطر ، يحتوي مسار "C: Documents ومعدة ... التنزيلات 0 Documents Downloads" ، والتي كانت القيمة غير الصالحة من التكرار السابق قبل أن أقوم بتجريد الأحرف غير الصالحة (التي شوهدت هنا على أنها " 0"! !
  3. الآن المسار هو fubar لأنني بدأت بسلسلة مشدودة وتزداد سوءًا.

لماذا يتم تعيين المسار القيمة غير صالحة من استدعاء الوظيفة السابقة (بعد تعيين سلسلة فارغة بشكل صحيح!) عندما أقوم بتعيين قيمة بشكل صريح؟ !!!!!

هل كانت مفيدة؟

المحلول

TextRenderer.MeasureText الطريقة هي أ واحد سيء - يغير السلسلة الفعلية التي تم تمريرها كمعلمة ، لذلك تقوم بتغيير السلسلة الفعلية المشار إليها بواسطة DataGridView. في الواقع يجعل سلسلة .NET متقلب.

يبدو أيضًا أن هذه الطريقة المضحكة لا تغير الفعلي Length من السلسلة ، ولكن مجرد الكتابة فوق أحد الشخصيات مع \0 للإشارة إلى نهاية السلسلة (مثل الأوتار المطلقة الفارغة في عادي C). هذه بعض الأشياء المضحكة!

يمكن أن يكون لهذا تأثير خطير على استقرار تطبيقك. إذا كنت تأخذ في الاعتبار أن .NET يستخدم سلسلة انتقال, ، يمكنك البدء في الحصول على جميع أنواع النتائج الغريبة ، كما لاحظت أن ثوابت السلسلة الخاصة بك لم تعد ثابتة.

الخطوة الأولى هي إنشاء نسخة من السلسلة الخاصة بك (مثيل جديد مع نفس الأحرف):

string Path = String.Copy(e.Value as string ?? "");

بدلاً من

string Path = (string)Row.Cells[1].Value;

هذا سيضمن أنه مهما كان الأمر TextRenderer هل ، ستظل السلسلة الأصلية دون تغيير.

بعد ذلك ، تحتاج إلى التخلص من الشحن الفارغ في السلسلة المعدلة.

من خلال القيام بهذا:

if (Path.IndexOf('\0') >= 0)
   e.Value = Path.Substring(0, Path.IndexOf('\0'));
else
   e.Value = Path;

ستقوم بإنشاء مثيل جديد لسلسلة نظيفة وتعديل (تركنا مؤقتًا Path نسخ لا يمكن الرجوع إليه لجمع القمامة).

نصائح أخرى

تحتاج إلى استخدام حدث cellformatting لتغيير القيمة المحددة قبل طباعته (لن يتم تعديل قيمة الكائن الأصلي). في حالتك ، يمكنك التحقق مما إذا كان العمود الأيمن عن طريق التحقق من متغير E.ColumnIndex وتغيير نص E.Value كما فعلت أدناه:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView1.DataSource = new List<Person>(new Person[] { new Person() { Name = "André", Adress = "Brazil" } });
    }

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        e.Value = e.Value + " modified";
    }
}

class Person
{
    public String Name { get; set; }
    public String Adress { get; set; }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top