WPF: Свяжите Набор с Набором к ListBox с группами

Вы можете отправлять приглашения на собрания по почте в Outlook, используя Стандарт iCal (RFC 5545)

Вы не можете отправлять элементы задач таким способом. Вы можете отправлять «Встречи», но они выглядят в перспективе как приложения .ics, которые должны приниматься «вслепую».

Приглашения на собрание появляются в Outlook с хорошим предварительным просмотром и могут быть приняты или отклонены. Программа отправки может изменить или отменить собрание после его отправки.

Легко создать действительный элемент iCal с помощью библиотеки DDay.iCal .Net

Приведенный ниже код является полным рабочим примером. Он создает строку с действительным приглашением на собрание iCal и отправляет ее по почте.

Код создает почту с:

  • текстовым телом для простых почтовых клиентов
  • HTML-текст для diplay в современных почтовых клиентах
  • iCal для приглашения на собрание в виде AlternateView (будет отображаться в Outlook)
  • приглашение на собрание iCal в качестве вложения (используется в почтовых клиентах, отличных от outlook)

Код показывает, как добавить:

  • текст описания в виде HTML выглядит лучше в outlook
  • Приоритет, видимость (публичный / частный / конфиденциальный)
  • необязательный органайзер (будет отображаться в outlook вместо отправителя почты)
  • необязательные участники
  • необязательный будильник
  • необязательные приложения к собранию. будет отображаться в календаре Outlook

Некоторые важные детали:

  • отправитель почты (или дополнительный организатор) и получатель почты должны отличаться, чтобы эта работа работала в Outlook
  • МЕТОД в .ics и МЕТОД в Mime.ContentType должны совпадать
  • Совещание должно состояться в будущем, чтобы сделать эту работу в перспективе
  • часть .ics должна быть последней частью alternateView в почте MIME

Точные подробности о том, как outlook интерпретирует файлы .ics, подробно описаны в [MS-OXCICAL]: Алгоритм преобразования объектов iCalendar в Appointment

Мы будем использовать эти сборки:

using System;
using System.IO;
using System.Net.Mail;
using DDay.iCal;
using DDay.iCal.Serialization.iCalendar;

Для DDay.iCal достаточно загрузить двоичные файлы DDay.iCal . Если вы хотите добавить некоторые функции, лучше всего взглянуть на исходники DDay.iCal, поскольку документация устарела, и источники содержат довольно полные тесты, в которых описаны все его функции.

const string filepath = @"C:\temp\ical.test.ics";
// use PUBLISH for appointments
// use REQUEST for meeting requests
const string METHOD = "REQUEST";

// Properties of the meeting request
// keep guid in sending program to modify or cancel the request later
Guid uid = Guid.Parse("2B127C67-73B3-43C5-A804-5666C2CA23C9");
string VisBetreff = "This is the subject of the meeting request";
string TerminVerantwortlicherEmail = "mr.asker@myorg.com";
string bodyPlainText = "This is the simple iCal plain text msg";
string bodyHtml = "This is the simple iCal HTML message";
string location = "Meeting room 101";
// 1: High
// 5: Normal
// 9: low
int priority = 1;
//=====================================
MailMessage message = new MailMessage();

message.From = new MailAddress("sender@myorg.com");
message.To.Add(new MailAddress(TerminVerantwortlicherEmail));
message.Subject = "[VIS-Termin] " + VisBetreff;

// Plain Text Version
message.Body = bodyPlainText;

// HTML Version
string htmlBody = bodyHtml;
AlternateView HTMLV = AlternateView.CreateAlternateViewFromString(htmlBody,
  new System.Net.Mime.ContentType("text/html"));

// iCal
IICalendar iCal = new iCalendar();
iCal.Method = METHOD;
iCal.ProductID = "My Metting Product";            

// Create an event and attach it to the iCalendar.
Event evt = iCal.Create();
evt.UID = uid.ToString();

evt.Class = "PUBLIC";
// Needed by Outlook
evt.Created = new iCalDateTime(DateTime.Now);

evt.DTStamp = new iCalDateTime(DateTime.Now);
evt.Transparency = TransparencyType.Transparent;

// Set the event start / end times
evt.Start = new iCalDateTime(2014, 10, 3, 8, 0, 0); 
evt.End = new iCalDateTime(2014, 10, 3, 8, 15, 0); 
evt.Location = location;

//var organizer = new Organizer("the.organizer@myCompany.com");
//evt.Organizer = organizer;

// Set the longer description of the event, plain text
evt.Description = bodyPlainText;

// Event description HTML text
// X-ALT-DESC;FMTTYPE=text/html
var prop = new CalendarProperty("X-ALT-DESC");
prop.AddParameter("FMTTYPE", "text/html");
prop.AddValue(bodyHtml);
evt.AddProperty(prop);

// Set the one-line summary of the event
evt.Summary = VisBetreff;
evt.Priority = priority;

//--- attendes are optional
IAttendee at = new Attendee("mailto:Peter.Black@MyOrg.com");
at.ParticipationStatus = "NEEDS-ACTION";
at.RSVP = true;
at.Role = "REQ-PARTICIPANT";
evt.Attendees.Add(at);

// Let’s also add an alarm on this event so we can be reminded of it later.
Alarm alarm = new Alarm();

// Display the alarm somewhere on the screen.
alarm.Action = AlarmAction.Display;

// This is the text that will be displayed for the alarm.
alarm.Summary = "Upcoming meeting: " + VisBetreff;

// The alarm is set to occur 30 minutes before the event
alarm.Trigger = new Trigger(TimeSpan.FromMinutes(-30));

//--- Attachments
string filename = "Test.docx";

// Add an attachment to this event
IAttachment attachment = new DDay.iCal.Attachment();
attachment.Data = ReadBinary(@"C:\temp\Test.docx");
attachment.Parameters.Add("X-FILENAME", filename);
evt.Attachments.Add(attachment);

iCalendarSerializer serializer = new iCalendarSerializer();
serializer.Serialize(iCal, filepath);

// the .ics File as a string
string iCalStr = serializer.SerializeToString(iCal);

// .ics as AlternateView (used by Outlook)
// text/calendar part: method=REQUEST
System.Net.Mime.ContentType calendarType = 
  new System.Net.Mime.ContentType("text/calendar");
calendarType.Parameters.Add("method", METHOD);
AlternateView ICSview =
  AlternateView.CreateAlternateViewFromString(iCalStr, calendarType);

// Compose
message.AlternateViews.Add(HTMLV);
message.AlternateViews.Add(ICSview); // must be the last part

// .ics as Attachment (used by mail clients other than Outlook)
Byte[] bytes = System.Text.Encoding.ASCII.GetBytes(iCalStr);
var ms = new System.IO.MemoryStream(bytes);
var a = new System.Net.Mail.Attachment(ms,
  "VIS-Termin.ics", "text/calendar");
message.Attachments.Add(a);     

// Send Mail
SmtpClient client = new SmtpClient();
client.Send(message);

Здесь функция ReadBinary ():

private static byte[] ReadBinary(string fileName)
{
    byte[] binaryData = null;
    using (FileStream reader = new FileStream(fileName,
      FileMode.Open, FileAccess.Read))
    {
        binaryData = new byte[reader.Length];
        reader.Read(binaryData, 0, (int)reader.Length);
    }
    return binaryData;
}

Самую простую настройку SmtpClient в конфигурационном файле можно получить следующим образом:


  ...
    
    
      
        
      
    
  
  ...

8
задан 22 May 2009 в 06:31
поделиться

2 ответа

Что ж, я не уверен, что вы хотите достичь именно этого, но вот способ, который вы можете попробовать:

Предполагая, что ваши классы такие:

public class Group
{
    public string Name { get; set; }
    public List<Contact> Contacts { get; set; }
}

public class Contact
{
    public string Name { get; set; }
    public bool IsOnline { get; set; }
}

Вы можете установить ListBox.ItemTemplate в качестве другого ListBox, привязанного к свойству «Контакты», например:

<CollectionViewSource x:Key="groups" Source="{Binding}" >
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Name" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

<DataTemplate x:Key="groupTemplate" DataType="Group">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}" />
    </StackPanel>
</DataTemplate>

<ListBox ItemsSource="{Binding Source={StaticResource groups}}">
    <ListBox.GroupStyle>
        <GroupStyle HeaderTemplate="{StaticResource groupTemplate}" />
    </ListBox.GroupStyle>
    <ListBox.ItemTemplate>
        <DataTemplate DataType="Contact">
            <ListBox ItemsSource="{Binding Contacts}">
                <ListBox.ItemTemplate>
                    <DataTemplate DataType="Contact">
                        <TextBlock Text="{Binding Name}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Вы должны немного стилизовать внутренний список.

Изменить : другое решение, используя TreeView

<DataTemplate DataType="Contact">
   <TextBlock Text="{Binding Name}" />
</DataTemplate>

<TreeView ItemsSource="{Binding Source={StaticResource groups}}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding Contacts}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
21
ответ дан 5 December 2019 в 05:46
поделиться

Если у вас есть копия Programming WPF , перейдите на страницу 221. Если нет, я подведу итог (в моем неумелом стиле)

Во-первых, вам не нужно вручную группировать Объекты Person.

Если каждый объект Person имеет свойство Group,

People people = // retrieve the List<Person> somehow
ICollectionView view = CollectionViewSource.GetDefaultView(people);
view.GroupDescriptions.Add( new PropertyGroupDescription("Group") );

все элементы управления, производные от ItemsControl, могут отображать сгруппированные элементы, поэтому

// the XAML
<ListBox ... ItemsSource={Binding}>
  <ListBox.GroupStyle>
    <x:Static Member="GroupStyle.Default" />
  </ListBox.GroupStyle>
</ListBox>

Вы также можете определить собственный GroupStyle и указать GroupStyle.HeaderTemplate для определения нового DataTemplate, который показывает настраиваемые атрибуты, такие как 'some PropertyValue (Count)' - привяжите один TextBlock к {Binding SomeProperty} , а другой к {Binding ItemCount}

HTH

8
ответ дан 5 December 2019 в 05:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: