3

昨日質問を投稿しましたが、正しく説明できなかったと思います。

もう一度やり直します。

これが私の目標です。

ここに画像の説明を入力してください

赤い吹き出しは着信メッセージを表し、青い吹き出しは発信メッセージを表します。これは、次のxamlコードでより正確に説明できます。次のコードは、実際のxamlコード(一部のDataTemplatesを含む)がコンパイルされたときに得られると予想されるものの説明にすぎないことに注意してください(WPFはDataTemplatesを使用してデータを自動的に入力します)。:

<ListBox>
    <ListBoxItem HorizontalAlignment="Right">
        <Grid Background="Blue">
            <TextBlock Text="Help me please!" FontSize="30"/>
        </Grid>
    </ListBoxItem>
    <ListBoxItem HorizontalAlignment="Left">
        <Grid Background="Red">
            <TextBlock Text="What do you want?" FontSize="30"/>
        </Grid>
    </ListBoxItem>
    <ListBoxItem HorizontalAlignment="Right">
        <Grid Background="Blue">
            <TextBlock Text="I want a ListBox" FontSize="30"/>
        </Grid>
    </ListBoxItem>
    <ListBoxItem HorizontalAlignment="Left">
        <Grid Background="Red">
            <TextBlock Text="Then?" FontSize="30"/>
        </Grid>
    </ListBoxItem>
    <ListBoxItem HorizontalAlignment="Right">
        <Grid Background="Blue">
            <TextBlock Text="But the Grid won't fill" FontSize="30"/>
        </Grid>
    </ListBoxItem>
</ListBox>

これを達成するために、私は次のように書きました。

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ListBoxItem>
                <Grid Background="{Binding Color}">
                    <TextBlock Text="{Binding Text}" FontSize="30"/>
                </Grid>
            </ListBoxItem>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

上記のコードではアライメントが指定されていないことに注意してください。テンプレートを使用してListBoxItemに個別に異なるアライメントを設定する方法が本当にわからないためです。したがって、これにより、デフォルトでは、すべての青と赤のグリッドがすべて左に配置される状況になります。

私の最初のアプローチには、データテンプレートセレクターが含まれています(着信メッセージのテンプレートは省略されています)。

<ListBox>
    <ListBox>
        <ListBox.ItemTemplate>
            <!-- local:MessageBubbleTemplateSelector.OutgoingMessageTemplate  -->
            <DataTemplate>
                <ListBoxItem>
                    <Grid>
                        <Grid Background="{Binding Color}" HorizontalAlignment="Right">
                            <TextBlock Text="{Binding Text}" FontSize="30"/>
                        </Grid>
                    </Grid>
                </ListBoxItem>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</ListBox>

しかし、これはうまくいきませんでした。Gridふきだしを包むものは自動的に拡大しないので、これの内側の位置合わせは重要GridGridはありませんでした(しっかりとはめ込まれています)。

そして、Grid内部を拡張する方法を探しに行きましたStackPanelが、運がありませんでした。

何時間ものグーグルと試行錯誤の末、私はItemsPanelTemplate自分のためにテンプレートを定義することにしました。Messageオブジェクトに、着信メッセージと発信メッセージを区別するのに役立つプロパティがあります。しかし、セレクターの作成方法がわかりません(記録として、GoogleはWindows Phone 8ではサポートされていない ItemsPanelTemplateと言っていました)。Style.Trigger

だから私の質問は:どのように異なるHorizo​​ntalAlignmentを設定するの ListBoxItemsですか?

ところで、ItemsPabelTemplateこのように見えます:

<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel />
    </ItemsPanelTemplate>
</ListBox.ItemsPanel>

ご理解のほどよろしくお願いいたします。私はすでにここで狂ったように必死です...これに多くの時間が無駄になりました...

4

5 に答える 5

5

注: 私は Phone SDK を持っていないので、通常の WPF アプリで間に合わせる必要がありました。あなたが言ったように、私はトリガーを使用していません。

だから私はこのようなシンプルなアプリをノックアップしました

ここに画像の説明を入力

コードは次のとおりです。

App.xaml.cs

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var mainvm = new MainWindowViewModel();
        var window = new MainWindow
        {
            DataContext = mainvm
        };
        window.Show();

        mainvm.Messages.Add(new OutgoingMessage{ MessageContent = "Help me please!"});

        mainvm.Messages.Add(new IncomingMessage { MessageContent = "What do you want" });

        mainvm.Messages.Add(new OutgoingMessage { MessageContent = "I want a ListBox" });

        mainvm.Messages.Add(new IncomingMessage { MessageContent = "Then?" });

        mainvm.Messages.Add(new OutgoingMessage { MessageContent = "But the Grid won't fill" });
    }
}

MainWindow.xaml

<Window x:Class="ChatUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ChatUI"
    Title="MainWindow" Height="350" Width="200">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:IncomingMessage}">
        <Grid Margin="0,10">
            <Border CornerRadius="8" Background="Red" BorderBrush="Black" BorderThickness="1" />
            <TextBlock Text="{Binding MessageContent}" HorizontalAlignment="Left" Margin="5" Foreground="White"/>
        </Grid>
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:OutgoingMessage}">
        <Grid Margin="0,10">
            <Border CornerRadius="8" Background="Blue" BorderBrush="Black" BorderThickness="1" />
            <TextBlock Text="{Binding MessageContent}" HorizontalAlignment="Right" Margin="5" Foreground="White"/>
        </Grid>
    </DataTemplate>
</Window.Resources>
<Grid Background="Black">
    <ItemsControl ItemsSource="{Binding Path=Messages}"/>
</Grid>

ViewModelBase.cs

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {
        Messages = new ObservableCollection<Message>();
    }
    public ObservableCollection<Message> Messages { get; protected set; }
}

Message.cs:

public abstract class Message : ViewModelBase
{
    private string _messageContent;

    public string MessageContent 
    {
        get
        {
            return this._messageContent;
        }
        set
        {
            this._messageContent = value;
            this.OnPropertyChanged("MessageContent");
        }
    }   
}

OutgoingMessage.cs

public class OutgoingMessage : Message
{
}

IncomingMessage.cs

public class IncomingMessage : Message
{
}

これがどのように機能するか アプリケーションの起動をオーバーライドして、ビューモデルを作成して UI を設定できるようにします。App.xaml.cs コードで、ウィンドウを作成して表示し、メッセージを追加していることがわかります。タイマーを使うつもりでしたが、怠けました。

MainWindow.xaml を見ると、2 つの DataTemplates が定義されていることがわかります。1 つは IncomingMessageViewModel を対象とし、もう 1 つは OutogingMessageViewModel を対象としています。ローカル プレフィックスは、アプリケーションの名前空間のエイリアスです。同じコレクションに受信メッセージと送信メッセージの両方を含めることができるように、基本型の Message クラスを含めることができる ItemsControl があります。これは、MainWindowViewModel クラスの Messages プロパティにバインドされています。着信メッセージと発信メッセージを 2 つの別個のクラスとして持つことが重要です。これがこの機能を実現する魔法だからです。

別の手法は、他の回答の1つが示唆するように、プロパティにスタイルセレクターがバインドされたプロパティを使用することですが、これはViewModelでUI固有のロジックを処理する必要があることを意味します(これは好きではありません)行う)。

いずれかの Message タイプの外観を変更するには、それぞれの DataTemplate で xaml コードを変更するだけです。

お役に立てれば。

于 2013-03-14T08:14:54.290 に答える
1

WPFでは、追加する必要があります

    <ListBox.ItemContainerStyle>
        <Style>
            <Setter Property="HorizontalAlignment" Value="{Binding WHATEVER}" />
        </Style>
    </ListBox.ItemContainerStyle>

ListBoxに追加し、「WHATEVER」をアイテムのプロパティに設定します。これは、配置が指定されています... Windows Phoneで機能するかどうかはわかりませんが、ItemContainerStyleについて言及していないため、試してみる価値はあります。 。

于 2013-03-14T03:31:05.493 に答える
1

Grid を使用する代わりに、代わりに Horizo​​ntalAlignment="Stretch" を指定した DockPanel を使用してください。

データの配置に関しては、ItemsSource を使用していると仮定すると、いくつかの回避策があります。

まず、Horizo​​ntalAlignment WPF プロパティをメッセージ クラスに追加するのが簡単です。メッセージ クラスは、Horizo​​ntalAlignment が左か右かを決定します。ただし、これにより、UI との依存関係がより高くなります。

コードは次のようになります。

<TextBlock Text="{Binding Text}" HorizontalAlignment="{Binding MessageHAlign}" />

第 2 に、より良い (またはクリーンな) 方法は、コンバーター (IValueConverter) を使用して Horizo​​ntalAlignment バインディングを行うことです。これは難しく、独自のコンバーターを定義する必要がありますが、コードはより整然としたものになります。次に、メッセージには、MessageType という名前の収入または結果メッセージの列挙があります。次に、コンバーターで次のように定義します。

public object Convert(object value, Type targetType, 
  object parameter, CultureInfo culture)
{
  if(parameter is MessageType){
    if(((MessageType)parameter) == MessageType.Income){
      return HorizontalAlignment.Left;
    }
    else{
      return HorizontalAlignment.Right;
    }
  }
}

上記のコードはテストされていないため、エラーを考慮してください。Converterの実装については、あちこちで検索してみてください。ソースのヘルプなしではまだコンバーターバインディングを生成できません:)

于 2013-03-14T05:19:18.203 に答える
0

それは私の汚い実例です

コードビハインド

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var l = new List<lItem>();

        for(int i=0;i<5;i++)
        {
        l.Add(new lItem(true,"aaa"+i));
        l.Add(new lItem(false,"bbb"+i));
        }

        sads.ItemsSource = l;

    }
}


public class lItem
{
    public string Text { get; set; }
    public Brush Color { get; set; }
    public HorizontalAlignment alig { get; set; }

    public lItem(bool ss, string str)
    {
        Text = str;
        Color = Brushes.Blue;
        alig = HorizontalAlignment.Right;

        if (ss)
        {
            Color = Brushes.Red;
            alig = HorizontalAlignment.Left;
        }
    }
}

Xaml

<ListBox Name="sads" Width="230">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ListBoxItem>
                        <Grid Width="200">
                            <Label Background="{Binding Color}" VerticalAlignment="Top" HorizontalAlignment="{Binding alig}" >
                                <TextBlock Text="{Binding Text}" FontSize="30"/>
                            </Label>
                        </Grid>
                    </ListBoxItem>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

ViewModel でビジュアル パーツを定義する代わりに、トリガーを使用することをお勧めします

于 2013-03-14T10:51:04.597 に答える
0

これを試して、着信に応じてプロパティを左に設定し、発信を右に設定します

<DataTemplate>

<ListBoxItem>

 <Grid>
 <Grid Background="{Binding Color}" HorizontalAlignment="{Binding Property}">
  <TextBlock Text="{Binding Text}" FontSize="30"/>
 </Grid>
 </Grid>
 </ListBoxItem>
 </DataTemplate>
于 2013-03-14T04:43:23.720 に答える