当我查看我的UI时,元素按预期运行,但是绑定到我的视图模型的任何东西都没有显示,但是绑定似乎在工作。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Fate.Views.GlobalChatPage"
x:DataType="viewmodels:GlobalChatPageViewModel"
xmlns:viewmodels="clr-namespace:Fate.ViewModels"
xmlns:converters="clr-namespace:Fate.Converters"
BackgroundColor="#242022">
<ContentPage.BindingContext>
<viewmodels:GlobalChatPageViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<converters:InverseBoolConverter x:Key="InverseBool" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Button x:Name="ConnectButton" Text="Connect" Command="{Binding ConnectCommand}" />
<Button x:Name="DisconnectButton" Text="Disconnect" Command="{Binding DisconnectCommand}" />
<Entry IsReadOnly="False" x:Name="namenameEntry" Text="{Binding Name}" Placeholder="Enter Namename" />
</StackLayout>
<ListView x:Name="MessagesListView" ItemsSource="{Binding Messages}" HasUnevenRows="true" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0" IsVisible="{Binding IsOwnMessage, Converter={StaticResource InverseBool}}">
<Label Text="{Binding Name}" />
<Frame x:Name="MessageFrame" CornerRadius="10" Padding="10" BackgroundColor="LightGray" HeightRequest="{Binding Source={x:Reference MessageLabel}, Path=Height}" Margin="0,0,0,20">
<Label x:Name="MessageLabel" Text="{Binding Message}"/>
</Frame>
</StackLayout>
<StackLayout Grid.Column="1" IsVisible="{Binding IsOwnMessage}">
<Label Text="{Binding Name}" HorizontalOptions="FillAndExpand" />
<Frame x:Name="MessageFrame2" CornerRadius="10" Padding="10" BackgroundColor="LightGray" HeightRequest="{Binding Source={x:Reference MessageLabel}, Path=Height}" Margin="0,0,0,20" HorizontalOptions="FillAndExpand">
<Label x:Name="MessageLabel2" Text="{Binding Message}" HorizontalOptions="FillAndExpand" />
</Frame>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout Orientation="Horizontal">
<Entry IsReadOnly="False" x:Name="MessageEntry" Text="{Binding Message}" HorizontalOptions="FillAndExpand" />
<Button x:Name="SendButton" Text="Send" Command="{Binding SendMessageCommand}" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
这是我的视图模型:
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Fate.ViewModels
{
public class GlobalChatPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
private string _message;
private ObservableCollection<string> _messages;
private bool _isConnected;
public bool _IsOwnMessage;
public bool _IsSystemMessage;
public bool IsSystemMessage
{
get
{
return _IsSystemMessage;
}
set
{
_IsSystemMessage = value;
OnPropertyChanged();
}
}
public bool IsOwnMessage
{
get
{
return _IsOwnMessage;
}
set
{
_IsOwnMessage = value;
OnPropertyChanged();
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
public string Message
{
get
{
return _message;
}
set
{
_message = value;
OnPropertyChanged();
}
}
public ObservableCollection<string> Messages
{
get
{
return _messages;
}
set
{
_messages = value;
OnPropertyChanged();
}
}
public bool IsConnected
{
get
{
return _isConnected;
}
set
{
_isConnected = value;
OnPropertyChanged();
}
}
private HubConnection hubConnection;
public Command SendMessageCommand { get; }
public Command ConnectCommand { get; }
public Command DisconnectCommand { get; }
public GlobalChatPageViewModel()
{
Messages = new ObservableCollection<string>();
SendMessageCommand = new Command(async () => { await SendMessage(Name, Message); });
ConnectCommand = new Command(async () => await Connect());
DisconnectCommand = new Command(async () => await Disconnect());
IsConnected = false;
hubConnection = new HubConnectionBuilder()
.WithUrl($"https://placeholderlink/chatHub")
.Build();
hubConnection.On<string>("JoinChat", (user) =>
{
Messages.Add($"{user} has joined the chat");
IsSystemMessage = true;
IsOwnMessage = false;
});
hubConnection.On<string>("LeaveChat", (user) =>
{
Messages.Add($"{user} has left the chat");
IsSystemMessage = true;
IsOwnMessage = false;
});
hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
Messages.Add($"{user}: {message}");
IsSystemMessage = false;
if (Name == user)
{
IsOwnMessage = true;
}
});
}
public async Task Connect()
{
if (IsConnected == false)
{
await hubConnection.StartAsync();
await hubConnection.InvokeAsync("JoinChat", Name);
IsConnected = true;
}
}
public async Task SendMessage(string user, string message)
{
await hubConnection.InvokeAsync("SendMessage", user, message);
}
public async Task Disconnect()
{
if (IsConnected == true)
{
await hubConnection.InvokeAsync("LeaveChat", Name);
await hubConnection.StopAsync();
IsConnected = false;
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
这是我的转换器:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Xamarin.Forms;
namespace Fate.Converters
{
public class InverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return !(bool)value;
}
}
}
我希望每个消息的文本都显示在页面上,如果来自其他人,则显示在左侧,如果来自用户,则显示在右侧,但文本根本不显示。我检查了绑定上下文,得到了智能感知,没有构建错误,但它仍然不显示。
1条答案
按热度按时间eanckbw91#
问题1
您正在通过应用
x:DataType
属性来使用compiled bindings。因此,您还需要为视图层次结构中更低的任何DataTemplate
设置正确的x:DataType
,因为绑定上下文会发生变化。当它显示YOUR_TYPE_HERE时,您需要指定与传递给
ItemsSource
的集合相同的类型,在您的示例中为string
(或其XAML等价物,即{x:Type x:String}
)。您还可以通过将DataTemplate
的x:DataType
类型设置为{x:Null}
来将绑定重置为经典绑定。问题2
在您的
DataTemplate
中,您绑定到了该上下文中不存在的属性,因为您的ListView
是用ObservableCollection<string>
填充的。例如,如果你想从ViewModel绑定到
Name
,你需要指定一个相对绑定:备选
一个快速的修复方法可能是简单地删除
ContentPage
上的x:DataType
。进一步观察
您多次绑定到
Name
,不清楚如何管理两个聊天参与者,以及每个参与者的姓名和消息来自何处,特别是因为ViewModel中只有一个Name
属性和一个Messages
集合。