>

C # 및 MVVM을 처음 사용하므로 문제가있을 수 있습니다. 나는 (LoginMenu라고 함) 창을 생성하고 윈도우의 1/3을 복용 채팅 UserControl이 추가되었습니다. 그런 다음 해당 채팅 userControl에 대한 ViewModel 및 모델을 작성했습니다. 내 채팅 모델이 클라이언트에서 오는 메시지를받을 때 소켓에 의해 업데이트됩니다. 대화 필드가 모델에서 업데이트되는 것처럼 보이지만 ChatViewModel의 PropertyChanged가 null입니다. 소켓 사용을 시작하기 전에 대화 텍스트 상자가 올바르게 업데이트되었습니다. 나는 내 소켓과 같은 스레드에서 실행되지 이후 내 UI 스레드가 업데이트 점점되지 않았기 때문에이 될 수 있음을 온라인으로 읽어 보시기 바랍니다. 내 ChatViewModel조차도 올바른 PropertyChanged 이벤트를 얻지 못하기 때문에 느낌이 들지 않습니다.

다음은 코드 스 니펫입니다. LoginMenu.xaml :

<Window.DataContext>
    <viewmodels:LoginMenuVM />
</Window.DataContext>
<Window.Resources>
    <DataTemplate x:Name="mainMenuOnlineTemplate" DataType="{x:Type viewmodels:MainMenuOnlineVM}">
        <views:MainMenuOnline DataContext="{Binding}"/>
    </DataTemplate>
    <DataTemplate x:Name="chatTemplate" DataType="{x:Type viewmodels:ChatVM}">
        <views:Chat DataContext="{Binding}"/>
    </DataTemplate>
</Window.Resources>

...

<views:Chat Grid.Column="1"></views:Chat>

LoginMenu.xaml.cs :

public partial class LoginMenu : Window
{
    public LoginMenu()
    {
        InitializeComponent();
        this.DataContext = new LoginMenuVM();
    }
}

LoginMenuViewModel :

public class LoginMenuVM : ViewModelBase
{
    private SocketService socketService = new SocketService();
    private User user = new User();
    private ChatVM chatVM = new ChatVM();

...

   public void ConnectUser(object obj)
    {
        if (NameIsIncorrect())
        {
            MessageBox.Show("Username is incorrect!");
            return;
        }
        else
        {
            AssignName(potentialName);
            socketService.Start(ipAdress);
            try
            {
                string authentification_informations = user.Name;
                socketService.SendDemand(authentification_informations);
                {
                    chatVM.connectSocket(socketService, user);
            } catch (Exception ex)
            {
            }
        }
    }

Chat.xaml :

<UserControl.DataContext>
    <viewmodels:ChatVM />
</UserControl.DataContext>
<DockPanel Background="White">
    <TextBlock DockPanel.Dock="Top" x:Name="name" Text="Name" Background="LightGray" />
    <TextBox DockPanel.Dock="Bottom" Height="50" Name="messageEntry" Text="{Binding ChatBoxMessage, UpdateSourceTrigger=PropertyChanged}" >
    <TextBox.InputBindings>
            <KeyBinding Key="Enter" Command="{Binding SendMessageCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
        </TextBox.InputBindings>
    </TextBox>
    <TextBlock x:Name="Conversation" Text="{Binding Path=Conversation, Mode=TwoWay}" />
</DockPanel>

ChatViewModel :

public class ChatVM : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged;
        private static SocketService socketService;
        private static User user;
        private static Chat chat;
        public string Conversation
        {
            get { return chat.Conversation; }
            set { NotifyPropertyChanged(); }
        }
        private string _chatBoxMessage = "Enter Message";
        public string ChatBoxMessage
        {
            get { return _chatBoxMessage; }
            set
            {
                _chatBoxMessage = value;
                NotifyPropertyChanged("ChatBoxMessage");
            }
        }
        public RelayCommand<object> SendMessageCommand { get; set; }
        public ChatVM()
        {
            chat = new Chat();
            SendMessageCommand = new RelayCommand<object>(SendMessage);
        }
        public void SendMessage(object obj)
        {
            if (socketService != null) {
                if (!string.IsNullOrWhiteSpace(ChatBoxMessage))
                {
                    socketService.SendDemand(user.Name + ":" + ChatBoxMessage);
                    MessageBox.Show(Conversation);
                }
                else {
                    MessageBox.Show("You can't send empty or only white space messages.");
                }
            }
            else {
                    MessageBox.Show("You can't send messages since you're not connected.");
            }
        }
        public void connectSocket (SocketService socketServiceTemp, User userTemp)
        {
            user = userTemp;
            socketService = socketServiceTemp;
            chat = socketService.GetChat();
            chat.PropertyChanged += Conversation_CollectionChanged;
        }
        private void Conversation_CollectionChanged(object sender, PropertyChangedEventArgs e)
        {
            Conversation = chat.Conversation;
        }
       protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (PropertyChanged != null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

Chat.cs :

public class Chat : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private string _conversation = "Test";
        public string Conversation
        {
            get { return _conversation; }
            set
            {
                _conversation = value;
                NotifyPropertyChanged();
            }
        }
        private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (PropertyChanged != null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

SocketService.cs :

private void TreatAnswer(IAsyncResult ar)
{
    int messageReceivedInInt = socket.EndReceive(ar);
    //Transform Bytes received to string
    App.Current.Dispatcher.BeginInvoke((Action)delegate
    {
        chat.Conversation += messageReceived;
        Thread.Sleep(100);
    });
    Thread.Sleep(100);
    socket.BeginReceive(byteMessage, 0, 2048, SocketFlags.None, TreatAnswer, socket);
}

사용하려고했습니다

App.Current.Dispatcher.BeginInvoke((Action)delegate
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            Thread.Sleep(100);
        });

Chat.cs NotifyPropertyChanged 및 ChatViewModel NotifyPropertyChanged 모두

위에서 언급했듯이 ChatViewModel의 NotifyPropertyChanged에 중단 점을 추가하면 PropertyChanged가 null입니다. 어쨌든이 코드를 작동시킬 수 있습니까? 작은 실수 인 것 같지만 찾을 수 없습니다.

수정 :

문제가 발견되었습니다. 전화해야 했어요 :

chat.PropertyChanged += new PropertyChangedEventHandler(Conversation_CollectionChanged);

ChatVM의 SendMessage 기능 내부에서 적절한 이벤트를 발생시킵니다.

  • 답변 # 1

    당신은 ChatVM의 그 어떤 인스턴스가 채팅 템플릿

    사용할 수 있도록하는 UI를 이야기하지 않습니다

    LoginMenuViewModel.cs

    private ChatVM chatVM = new ChatVM();
    Public ChatVM ChatVMProperty // We need a property to bind
    {
        get { return chatVM; }
        set { chatVM = value; 
              /* Call Notify Property Changed if 
               you are assigning after constructor 
               getting called */ 
            }
    }
    
    

    LoginMenu.xaml

    <DataTemplate x:Name="chatTemplate" DataType="{x:Type viewmodels:ChatVM}">
        <views:Chat DataContext="{Binding ChatVMProperty}"/>
    </DataTemplate>
    
    

  • 이전 pnpm 상점에서 패키지를 제거하거나 강제로 다시 다운로드하는 방법은 무엇입니까?
  • 다음 ruby on rails - Capybara 및 셀레늄 웹 드라이버로 새 개인 창 열기